mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 01:58:20 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0ad50f5ae | ||
|
|
4b8874ceb9 | ||
|
|
cf19e3e46a | ||
|
|
1429a7b3ef | ||
|
|
7486a2cd51 | ||
|
|
fd0da9c0df | ||
|
|
6d36584ff2 | ||
|
|
f422edaf15 | ||
|
|
1473eafd1a | ||
|
|
cac86197cb | ||
|
|
006c44ff5d | ||
|
|
be3e109309 | ||
|
|
2bad436abf | ||
|
|
7ab4630cc9 | ||
|
|
5dab97b6d4 | ||
|
|
b38a442386 | ||
|
|
0708310041 | ||
|
|
cd27a53345 | ||
|
|
416e173448 | ||
|
|
d73523864a | ||
|
|
eb69a42863 | ||
|
|
651826b660 | ||
|
|
6dcdf91458 | ||
|
|
a6586cafb2 | ||
|
|
e496ee7a80 | ||
|
|
a4b6803556 | ||
|
|
9c72fef086 | ||
|
|
10d1c6da18 | ||
|
|
5ed84e04f8 | ||
|
|
25fa6acc4d | ||
|
|
9a46c5afc4 | ||
|
|
97ae5f7b1e | ||
|
|
1c7c277432 | ||
|
|
70ca8c4016 | ||
|
|
73507d5f4e | ||
|
|
d2f811eff3 | ||
|
|
2e5181666f | ||
|
|
5c0ce6b83e | ||
|
|
f6b3019796 | ||
|
|
dd04aeba1c | ||
|
|
57c0dcdc29 | ||
|
|
6d39c6f646 | ||
|
|
5a3c646307 | ||
|
|
0da47c51de | ||
|
|
120079b0a6 | ||
|
|
3da887c58f | ||
|
|
4922bc4890 | ||
|
|
ed161b240e | ||
|
|
531bfbd61f | ||
|
|
cd0b12ed1a | ||
|
|
0dc0758574 | ||
|
|
bcae817215 | ||
|
|
b850b14300 | ||
|
|
a277170c9a | ||
|
|
711bd095db | ||
|
|
d55b019284 | ||
|
|
f2af97711b | ||
|
|
b46ac13504 | ||
|
|
cee6871710 | ||
|
|
b74d8c1acd | ||
|
|
fc595a7111 | ||
|
|
bf7843833f | ||
|
|
251dcb07eb | ||
|
|
b407327972 | ||
|
|
aee50b1327 | ||
|
|
4de2cf34e6 | ||
|
|
52f1db7220 | ||
|
|
c995838e5c | ||
|
|
539bddce8c | ||
|
|
002df0f16c | ||
|
|
be16bcdcd3 | ||
|
|
cb9a0466f1 | ||
|
|
543c93f623 | ||
|
|
3f0bcdc3ef | ||
|
|
0d7c265392 | ||
|
|
022536cab6 | ||
|
|
2278327eba | ||
|
|
37d40e087f | ||
|
|
179e048bba | ||
|
|
c2590cf7a0 | ||
|
|
89d1e5b8f2 | ||
|
|
5e60e5ad10 | ||
|
|
6b06a8176d | ||
|
|
14d036b68d | ||
|
|
fae0c0286f | ||
|
|
d6ff4c754e | ||
|
|
f44d88707e | ||
|
|
fc96af058b | ||
|
|
bd6069deb5 | ||
|
|
e9735a7738 | ||
|
|
0ea10c8631 | ||
|
|
e522aa3a07 | ||
|
|
d7b88734cd | ||
|
|
da8f5009fd | ||
|
|
ef9776755e | ||
|
|
da336b3ea8 | ||
|
|
69bee64a59 | ||
|
|
f7ff77d865 | ||
|
|
648bf6555c | ||
|
|
60cb435cb4 | ||
|
|
64c284003d | ||
|
|
3d2d04b25e | ||
|
|
5af19b7eed | ||
|
|
8111462789 | ||
|
|
f52f65b2e3 | ||
|
|
997ce29ddc | ||
|
|
d38700687a | ||
|
|
0f89140882 | ||
|
|
0cee831da3 | ||
|
|
b41f91c658 | ||
|
|
e7329b7cba | ||
|
|
c19ac8729d | ||
|
|
9d2f993364 | ||
|
|
31dab8a75d | ||
|
|
7a06760e6f | ||
|
|
9209ea63a7 | ||
|
|
84b9b8ed87 | ||
|
|
e557058ac8 | ||
|
|
467a332e38 | ||
|
|
7ae556463a | ||
|
|
c424352a0a | ||
|
|
d5910e2673 | ||
|
|
9b7c8db846 | ||
|
|
4a6fd3d910 | ||
|
|
38df0a4186 | ||
|
|
1c0adb556d | ||
|
|
8aca94f951 | ||
|
|
38e3ab57a6 | ||
|
|
672ccda37c | ||
|
|
9849b4c7ba | ||
|
|
3421b9a580 | ||
|
|
29d695f4c9 | ||
|
|
7d6835c0dd | ||
|
|
05197afca2 | ||
|
|
bc353f454b | ||
|
|
7bc24888fe | ||
|
|
59ac141e49 | ||
|
|
60b68d7152 | ||
|
|
a5b483f2d4 | ||
|
|
d3efa47f81 | ||
|
|
7822917fc2 | ||
|
|
81ee11a16e | ||
|
|
f155205eb0 | ||
|
|
e46ef487a8 | ||
|
|
afc07b9339 | ||
|
|
edb8fef06c | ||
|
|
b75a4654cf | ||
|
|
fe3216e961 | ||
|
|
174d288e66 | ||
|
|
9f9b240f3d | ||
|
|
726f04e8aa | ||
|
|
556697cbd8 | ||
|
|
3ee3736a01 | ||
|
|
01bd7d1008 | ||
|
|
32321ab1e9 | ||
|
|
3b4fcd8575 | ||
|
|
6ba3b448f3 | ||
|
|
91e167caaf | ||
|
|
ccbae7799e | ||
|
|
af24c19db3 | ||
|
|
950a1b310b | ||
|
|
daca5499b9 | ||
|
|
2526a9b8c7 | ||
|
|
7549a5755e | ||
|
|
795d295590 | ||
|
|
3f3cb0650b | ||
|
|
acd8900071 | ||
|
|
6c60793f3a | ||
|
|
ad97775370 | ||
|
|
0b5f84dd20 | ||
|
|
27b5deefb1 | ||
|
|
ecb2ef7c39 | ||
|
|
304cf8869c | ||
|
|
3e0ddf70e9 | ||
|
|
5005f2e446 | ||
|
|
bc8532688b | ||
|
|
09811e739f | ||
|
|
24988f2351 | ||
|
|
b46f763ee7 | ||
|
|
87708c5d6e | ||
|
|
8c2bf341e9 | ||
|
|
6cc9e08f1b | ||
|
|
bfb85fe6d0 | ||
|
|
2cc1d5ac4c | ||
|
|
6e582d245b | ||
|
|
2395a9eced | ||
|
|
0060940d84 | ||
|
|
1ea01fc905 | ||
|
|
c7a8cd21e9 | ||
|
|
224c12f54d | ||
|
|
be29b709b7 | ||
|
|
e14ae1642e | ||
|
|
40991ec992 | ||
|
|
97bb5a3a80 | ||
|
|
bc3d84341d | ||
|
|
c937fbb222 | ||
|
|
cdf9e8c8a3 | ||
|
|
4c40c500b8 | ||
|
|
3665232d66 | ||
|
|
775944a2d0 | ||
|
|
994e1f4386 | ||
|
|
3733b43a8f | ||
|
|
134ffee519 | ||
|
|
6c90f830d9 | ||
|
|
14731d61fa | ||
|
|
418bcb39af | ||
|
|
3f49889841 | ||
|
|
1ad2f530f9 | ||
|
|
654ceaba7d | ||
|
|
6a3330d7c9 | ||
|
|
945699694e | ||
|
|
aab4ee4072 | ||
|
|
8f5678882d | ||
|
|
9fa6725067 | ||
|
|
06f9a5b627 | ||
|
|
446a1f7c5a | ||
|
|
df08b541af | ||
|
|
e0fabd1d49 | ||
|
|
9cf2bdc9a8 | ||
|
|
ed5b763a0c | ||
|
|
22b63d0b98 | ||
|
|
6f7d0cb1c3 | ||
|
|
b69f3d2488 |
No files matched your search
@@ -21,8 +21,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: support ape bins
|
||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||
- name: support ape bins 1
|
||||
run: sudo cp build/bootstrap/ape.elf /usr/bin/ape
|
||||
|
||||
- name: support ape bins 2
|
||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||
|
||||
- name: make matrix
|
||||
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
||||
@@ -60,7 +60,7 @@
|
||||
# build/config.mk
|
||||
|
||||
SHELL = build/bootstrap/cocmd.com
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
.SUFFIXES:
|
||||
@@ -68,6 +68,12 @@ MAKEFLAGS += --no-builtin-rules
|
||||
.FEATURES: output-sync
|
||||
.PHONY: all o bins check test depend tags
|
||||
|
||||
ifneq ($(m),)
|
||||
ifeq ($(MODE),)
|
||||
MODE := $(m)
|
||||
endif
|
||||
endif
|
||||
|
||||
all: o
|
||||
o: o/$(MODE)
|
||||
|
||||
@@ -86,9 +92,10 @@ o/$(MODE): \
|
||||
.UNVEIL = \
|
||||
libc/integral \
|
||||
libc/disclaimer.inc \
|
||||
rwc:/dev/shm \
|
||||
rx:build/bootstrap \
|
||||
rx:o/third_party/gcc \
|
||||
/proc/self/status \
|
||||
/proc/stat \
|
||||
rw:/dev/null \
|
||||
w:o/stack.log \
|
||||
/etc/hosts \
|
||||
@@ -115,11 +122,13 @@ include third_party/compiler_rt/compiler_rt.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/zlib/zlib.mk # │
|
||||
include third_party/double-conversion/dc.mk # │
|
||||
include libc/elf/elf.mk # │
|
||||
include ape/ape.mk # │
|
||||
include libc/fmt/fmt.mk # │
|
||||
include libc/vga/vga.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||
include libc/crt/crt.mk # │ You can issue system calls
|
||||
include third_party/nsync/nsync.mk # │
|
||||
@@ -128,6 +137,7 @@ include libc/mem/mem.mk #─┐
|
||||
include libc/zipos/zipos.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/gdtoa/gdtoa.mk # │ You can now use stdio
|
||||
include libc/time/time.mk # │ You can finally call malloc()
|
||||
include third_party/nsync/mem/mem.mk # │
|
||||
include libc/thread/thread.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
@@ -142,7 +152,6 @@ include dsp/mpeg/mpeg.mk # │
|
||||
include dsp/dsp.mk # │
|
||||
include third_party/zlib/gz/gz.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
include libc/sock/sock.mk #─┐
|
||||
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||
@@ -153,6 +162,7 @@ include net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/tidy/tidy.mk
|
||||
include third_party/third_party.mk
|
||||
include third_party/nsync/testing/testing.mk
|
||||
include libc/testlib/testlib.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include tool/args/args.mk
|
||||
@@ -160,11 +170,14 @@ include test/tool/args/test.mk
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/maxmind/maxmind.mk
|
||||
include net/finger/finger.mk
|
||||
include third_party/double-conversion/double-conversion.mk
|
||||
include third_party/double-conversion/test/test.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/tr/tr.mk
|
||||
include third_party/sed/sed.mk
|
||||
include third_party/awk/awk.mk
|
||||
include third_party/hiredis/hiredis.mk
|
||||
include third_party/make/make.mk
|
||||
include third_party/ctags/ctags.mk
|
||||
include third_party/finger/finger.mk
|
||||
include third_party/argon2/argon2.mk
|
||||
include third_party/smallz4/smallz4.mk
|
||||
@@ -181,6 +194,7 @@ include third_party/python/python.mk
|
||||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include tool/curl/curl.mk
|
||||
include examples/examples.mk
|
||||
include examples/pyapp/pyapp.mk
|
||||
include examples/pylife/pylife.mk
|
||||
@@ -195,6 +209,7 @@ include tool/hash/hash.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/tool.mk
|
||||
include net/turfwar/turfwar.mk
|
||||
include test/libc/tinymath/test.mk
|
||||
include test/libc/intrin/test.mk
|
||||
include test/libc/mem/test.mk
|
||||
@@ -265,101 +280,103 @@ o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS
|
||||
o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
|
||||
TAGS: .UNSANDBOXED = 1
|
||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
|
||||
TAGS: private .UNSANDBOXED = 1
|
||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) o/$(MODE)/third_party/ctags/ctags.com
|
||||
@$(RM) $@
|
||||
@$(TAGS) $(TAGSFLAGS) -L $< -o $@
|
||||
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
HTAGS: .UNSANDBOXED = 1
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
|
||||
HTAGS: private .UNSANDBOXED = 1
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS) o/$(MODE)/third_party/ctags/ctags.com
|
||||
@$(RM) $@
|
||||
@build/htags -L $< -o $@
|
||||
@build/htags o/$(MODE)/third_party/ctags/ctags.com -L $< -o $@
|
||||
|
||||
loc: .UNSANDBOXED = 1
|
||||
loc: private .UNSANDBOXED = 1
|
||||
loc: o/$(MODE)/tool/build/summy.com
|
||||
find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
NET_HTTP \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
LIBC_TIME \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_MUSL \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_REGEX \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_RUNTIME \
|
||||
THIRD_PARTY_NSYNC \
|
||||
LIBC_ELF \
|
||||
LIBC_CALLS \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_NT_PSAPI \
|
||||
LIBC_NT_POWRPROF \
|
||||
LIBC_NT_PDH \
|
||||
LIBC_NT_GDI32 \
|
||||
LIBC_NT_COMDLG32 \
|
||||
LIBC_NT_URL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_THREAD \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_VGA
|
||||
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
NET_HTTP \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
LIBC_TIME \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_MUSL \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_REGEX \
|
||||
LIBC_THREAD \
|
||||
THIRD_PARTY_NSYNC_MEM \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_RUNTIME \
|
||||
THIRD_PARTY_NSYNC \
|
||||
LIBC_ELF \
|
||||
LIBC_CALLS \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_VGA \
|
||||
LIBC_NT_PSAPI \
|
||||
LIBC_NT_POWRPROF \
|
||||
LIBC_NT_PDH \
|
||||
LIBC_NT_GDI32 \
|
||||
LIBC_NT_COMDLG32 \
|
||||
LIBC_NT_URL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_NT_SYNCHRONIZATION \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NEXGEN32E
|
||||
|
||||
COSMOPOLITAN_HEADERS = \
|
||||
APE \
|
||||
LIBC \
|
||||
LIBC_CALLS \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_NSYNC \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
LIBC_VGA \
|
||||
NET_HTTP \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_ZLIB_GZ \
|
||||
COSMOPOLITAN_HEADERS = \
|
||||
APE \
|
||||
LIBC \
|
||||
LIBC_CALLS \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_NSYNC \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
LIBC_VGA \
|
||||
NET_HTTP \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_REGEX
|
||||
|
||||
o/$(MODE)/cosmopolitan.a: \
|
||||
o/$(MODE)/cosmopolitan.a: \
|
||||
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||
|
||||
o/cosmopolitan.h: \
|
||||
@@ -370,7 +387,7 @@ o/cosmopolitan.h: \
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >$@
|
||||
|
||||
o/cosmopolitan.html: .UNSANDBOXED = 1
|
||||
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))) \
|
||||
@@ -389,6 +406,15 @@ $(SRCS): \
|
||||
libc/integral/lp64arg.inc \
|
||||
libc/integral/lp64.inc
|
||||
|
||||
.PHONY: toolchain
|
||||
toolchain: o/cosmopolitan.h \
|
||||
o/$(MODE)/ape/public/ape.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape-copy-self.o \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o \
|
||||
o/$(MODE)/cosmopolitan.a
|
||||
|
||||
# UNSPECIFIED PREREQUISITES TUTORIAL
|
||||
#
|
||||
# A build rule must exist for all files that make needs to consider in
|
||||
@@ -413,9 +439,9 @@ $(SRCS):
|
||||
$(HDRS):
|
||||
$(INCS):
|
||||
.DEFAULT:
|
||||
@$(ECHO) >&2
|
||||
@$(ECHO) NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
|
||||
@$(ECHO) >&2
|
||||
@$(ECHO)
|
||||
@$(ECHO) NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@
|
||||
@$(ECHO)
|
||||
$(RM) o/$(MODE)/depend
|
||||
|
||||
-include o/$(MODE)/depend
|
||||
@@ -23,11 +23,11 @@ If you're doing your development work on Linux or BSD then you need just
|
||||
five files to get started. Here's what you do on Linux:
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.0.1.zip
|
||||
unzip cosmopolitan-amalgamation-2.0.1.zip
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.2.zip
|
||||
unzip cosmopolitan-amalgamation-2.2.zip
|
||||
printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs -gdwarf-4 \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -Wl,--gc-sections \
|
||||
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||
objcopy -S -O binary hello.com.dbg hello.com
|
||||
@@ -57,9 +57,13 @@ sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status'
|
||||
|
||||
Since we used the `ape-no-modify-self.o` bootloader (rather than
|
||||
`ape.o`) your executable will not modify itself when it's run. What
|
||||
it'll instead do, is extract a 4kb program to `${TMPDIR:-${HOME:-.}}`
|
||||
that maps your program into memory without needing to copy it. It's
|
||||
possible to install the APE loader systemwide as follows.
|
||||
it'll instead do, is extract a 4kb program (the [APE loader](https://justine.lol/apeloader/))
|
||||
to `${TMPDIR:-${HOME:-.}}` that maps your program into memory without
|
||||
needing to copy it. The APE loader must be in an executable location
|
||||
(e.g. not stored on a `noexec` mount) for it to run. See below for
|
||||
alternatives:
|
||||
|
||||
It's possible to install the APE loader systemwide as follows.
|
||||
|
||||
```sh
|
||||
# System-Wide APE Install
|
||||
@@ -100,7 +104,7 @@ heavyweight features like tracing to your binaries by default. In that
|
||||
case, you may want to consider using our build system:
|
||||
|
||||
```sh
|
||||
make -j8 MODE=tiny
|
||||
make m=tiny
|
||||
```
|
||||
|
||||
Which will cause programs such as `hello.com` and `life.com` to shrink
|
||||
@@ -155,7 +159,7 @@ cd cosmopolitan
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16
|
||||
build/bootstrap/make.com
|
||||
o//examples/hello.com
|
||||
find o -name \*.com | xargs ls -rShal | less
|
||||
```
|
||||
@@ -174,7 +178,7 @@ having minimal deterministic builds. For example, if you wanted to build
|
||||
only hello.com then you could do that as follows:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 o//examples/hello.com
|
||||
build/bootstrap/make.com o//examples/hello.com
|
||||
```
|
||||
|
||||
Sometimes it's desirable to build a subset of targets, without having to
|
||||
@@ -183,7 +187,7 @@ directory name. For example, if you wanted to build only the targets and
|
||||
subtargets of the chibicc package including its tests, you would say:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 o//third_party/chibicc
|
||||
build/bootstrap/make.com o//third_party/chibicc
|
||||
o//third_party/chibicc/chibicc.com --help
|
||||
```
|
||||
|
||||
@@ -191,18 +195,19 @@ 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
|
||||
build/bootstrap/make.com -j16 MODE=tiny
|
||||
build/bootstrap/make.com m=tiny
|
||||
```
|
||||
|
||||
Here's some other build modes you can try:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 MODE=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com -j16 MODE=asan # production memory safety
|
||||
build/bootstrap/make.com -j16 MODE=opt # -march=native optimizations
|
||||
build/bootstrap/make.com -j16 MODE=rel # traditional release binaries
|
||||
build/bootstrap/make.com -j16 MODE=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com -j16 MODE=tinylinux # tiniest linux-only 4kb binaries
|
||||
build/bootstrap/make.com m=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com m=asan # production memory safety
|
||||
build/bootstrap/make.com m=opt # -march=native optimizations
|
||||
build/bootstrap/make.com m=rel # traditional release binaries
|
||||
build/bootstrap/make.com m=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com m=fastbuild # build 28% faster w/o debugging
|
||||
build/bootstrap/make.com m=tinylinux # tiniest linux-only 4kb binaries
|
||||
```
|
||||
|
||||
For further details, see [//build/config.mk](build/config.mk).
|
||||
@@ -244,21 +249,27 @@ gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| Windows | Vista | 2006 |
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Windows | 8 [1] | 2012 |
|
||||
| Mac OS X | 15.6 | 2018 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
|
||||
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
|
||||
for a community supported version of Cosmopolitan that works on Windows
|
||||
Vista and Windows 7.
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Funding for this project is crowdsourced using
|
||||
[GitHub Sponsors](https://github.com/sponsors/jart) and
|
||||
[Patreon](https://www.patreon.com/jart). Your support is what makes this
|
||||
project possible. Thank you! We'd also like to give special thanks to
|
||||
the following individuals:
|
||||
the following groups and individuals:
|
||||
|
||||
- [Joe Drumgoole](https://github.com/jdrumgoole)
|
||||
- [Rob Figueiredo](https://github.com/robfig)
|
||||
- [Wasmer](https://wasmer.io/)
|
||||
|
||||
For publicly sponsoring our work at the highest tier.
|
||||
@@ -35,11 +35,11 @@
|
||||
#include "ape/macros.internal.h"
|
||||
#include "ape/notice.inc"
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
#include "libc/nexgen32e/vidya.internal.h"
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
@@ -113,7 +113,33 @@ cstr: .endobj cstr,globl,hidden # ←for gdb readability
|
||||
//
|
||||
// @param dl is drive number
|
||||
// @noreturn
|
||||
ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
|
||||
ape_mz:
|
||||
#if SupportsWindows() || SupportsMetal()
|
||||
.asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
|
||||
// # in real mode
|
||||
// dec %bp
|
||||
// pop %dx
|
||||
// jno 0x4a
|
||||
// jo 0x4a
|
||||
//
|
||||
// # in legacy mode
|
||||
// push %ebp
|
||||
// pop %edx
|
||||
// jno 0x4a
|
||||
// jo 0x4a
|
||||
//
|
||||
// # 64-bit mode
|
||||
// rex.WRB
|
||||
// pop %r10
|
||||
// jno 0x4a
|
||||
// jo 0x4a
|
||||
#else
|
||||
// Avoid virus scanner reputation damage when targeting System Five.
|
||||
.asciz "jartsr='\n" # Justine Alexandra Roberts Tunney
|
||||
// push $0x61
|
||||
// jb 0x78
|
||||
// jae 0x78
|
||||
#endif
|
||||
.short 0x1000 # MZ: lowers upper bound load / 16
|
||||
.short 0xf800 # MZ: roll greed on bss
|
||||
.short 0 # MZ: lower bound on stack segment
|
||||
@@ -126,11 +152,15 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
|
||||
.org 0x24 # MZ: bytes reserved for you
|
||||
.ascii "JT" # MZ: OEM identifier
|
||||
.short 0 # MZ: OEM information
|
||||
.ascii "' <<'@'\n"
|
||||
.org 0x40-4 # MZ: bytes reserved for you
|
||||
#if SupportsWindows() || SupportsMetal()
|
||||
.long RVA(ape_pe) # PE: the new technology
|
||||
#else
|
||||
.long 0
|
||||
.org 0x78
|
||||
pop %rax
|
||||
jmp _start
|
||||
#endif
|
||||
.endfn ape_mz,globl,hidden
|
||||
|
||||
@@ -236,8 +266,9 @@ pc: cld
|
||||
#endif
|
||||
ljmp $0,$REAL(1f)
|
||||
1: mov %cx,%ds
|
||||
mov $IMAGE_BASE_REAL-0x0500,%cx # clears bss
|
||||
mov $0x0500>>4,%ax # struct mman
|
||||
.set mm,0x0500 # struct mman
|
||||
mov $IMAGE_BASE_REAL-mm,%cx # clears bss
|
||||
mov $mm>>4,%ax
|
||||
mov %ax,%es
|
||||
xor %ax,%ax
|
||||
xor %di,%di
|
||||
@@ -250,8 +281,10 @@ pc: cld
|
||||
xor %cx,%cx # current cylinder
|
||||
xor %dh,%dh # current head
|
||||
mov $v_ape_realsectors,%di # total sectors
|
||||
sub $v_ape_realslacksectors,%di
|
||||
3: call pcread
|
||||
mov %es,%si # addr += 512
|
||||
add $512>>4,%si
|
||||
mov %si,%es
|
||||
dec %di
|
||||
jnz 3b
|
||||
6: ljmp $0,$REAL(realmodeloader)
|
||||
@@ -329,7 +362,7 @@ dsknfo: push %bx
|
||||
movpp %es,%ds
|
||||
xor %si,%si
|
||||
mov %si,%es
|
||||
mov $0x1510,%si # mman::pc_drive_base_table
|
||||
mov $mm+"struct mman::pc_drive_base_table",%si
|
||||
xchg %si,%di
|
||||
movsw #→ headunloadtime, headloadtime
|
||||
movsw #→ shutofftime, bytespersector
|
||||
@@ -340,6 +373,7 @@ dsknfo: push %bx
|
||||
pop %ds
|
||||
xchg %bx,%ax
|
||||
stosw #→ pc_drive_type, pc_drive_last_sector
|
||||
scasb
|
||||
xchg %cx,%ax
|
||||
stosw #→ pc_drive_last_cylinder
|
||||
xchg %dx,%ax
|
||||
@@ -378,15 +412,12 @@ pcread: push %ax
|
||||
pop %cx
|
||||
pop %ax
|
||||
jc 9f
|
||||
mov %es,%si # addr += 512
|
||||
add $512>>4,%si
|
||||
mov %si,%es
|
||||
inc %al # ++sector
|
||||
cmp 0x151c,%al # mman::pc_drive_last_sector
|
||||
cmp mm+"struct mman::pc_drive_last_sector",%al
|
||||
jbe 2f
|
||||
mov $1,%al
|
||||
inc %dh # ++head
|
||||
cmp 0x1520,%dh # mman::pc_drive_last_head
|
||||
cmp mm+"struct mman::pc_drive_last_head",%dh
|
||||
jbe 2f
|
||||
xor %dh,%dh
|
||||
inc %cx # ++cylinder
|
||||
@@ -485,19 +516,19 @@ ape.mbrpad:
|
||||
ape_disk:
|
||||
.stub ape.diskid,quad
|
||||
.org 0x1be,0x00
|
||||
.macro .partn x
|
||||
.stub ape.part\x\().status,byte # 0=absent / 0x80=present
|
||||
.stub ape.part\x\().first.head,byte # in low 6 bits
|
||||
.stub ape.part\x\().first.cylinder,byte
|
||||
.stub ape.part\x\().first.sector,byte
|
||||
.stub ape.part\x\().filesystem,byte
|
||||
.stub ape.part\x\().last.head,byte
|
||||
.stub ape.part\x\().last.cylinder,byte
|
||||
.stub ape.part\x\().last.sector,byte
|
||||
.stub ape.part\x\().lba,long # c₀*Cₙ + h₀*Hₙ + s₀*Sₙ
|
||||
.stub ape.part\x\().sector.count,long # sectors are 512 bytes
|
||||
.macro .partn x:req sta h0 s0 c0 fs h9 s9 c9 lba0 nsec
|
||||
.stub ape.part\x\().status,byte,\sta # 0=non-boot / 0x80=active
|
||||
.stub ape.part\x\().first.head,byte,\h0
|
||||
.stub ape.part\x\().first.sector,byte,\s0 # in low 6 bits
|
||||
.stub ape.part\x\().first.cylinder,byte,\c0
|
||||
.stub ape.part\x\().filesystem,byte,\fs
|
||||
.stub ape.part\x\().last.head,byte,\h9
|
||||
.stub ape.part\x\().last.sector,byte,\s9
|
||||
.stub ape.part\x\().last.cylinder,byte,\c9
|
||||
.stub ape.part\x\().lba,long,\lba0 # c₀*Cₙ + h₀*Hₙ + s₀*Sₙ
|
||||
.stub ape.part\x\().sector.count,long,\nsec # sectors are 512 bytes
|
||||
.endm
|
||||
.partn 1
|
||||
.partn 1,0x80,0,1,0,0x7f,0xff,0xff,0xff,0,0xffffffff
|
||||
.partn 2
|
||||
.partn 3
|
||||
.partn 4
|
||||
@@ -549,7 +580,10 @@ ape_disk:
|
||||
the bourne executable & linkable format */
|
||||
|
||||
#if SupportsWindows() || SupportsMetal() || SupportsXnu()
|
||||
apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
apesh: .ascii "\n@\n#'\"\n" # sixth edition shebang
|
||||
.ascii "m=\"$(uname -m)\"\n"
|
||||
|
||||
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
|
||||
// Until all operating systems can be updated to support APE,
|
||||
// we have a beautiful, yet imperfect workaround, which is to
|
||||
// modify the binary to follow the local system's convention.
|
||||
@@ -651,17 +685,332 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "exec \"$o\" \"$@\"\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "R=$?\n"
|
||||
.ascii "if [ \"$(uname -m)\" != x86_64 ]; then\n"
|
||||
.ascii "Q=\"$(command -v qemu-x86_64)\" &&\n"
|
||||
.ascii "exec \"$Q\" \"$o\" \"$@\"\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "else\n" # means argv[0] was wrong
|
||||
.ascii " exec \"$o\" \"$@\"\n" # so do a path resolution
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "exit $?\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exit $R\n"
|
||||
|
||||
.ascii "PHDRS='' <<'@'\n"
|
||||
.endobj apesh
|
||||
// elf program headers get inserted here
|
||||
// because they need to be in the first 4096 bytes
|
||||
.section .emush,"a",@progbits
|
||||
emush: .ascii "\n@\n#'\"\n"
|
||||
.ascii "s=\"$(uname -s)\"\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.1\"\n"
|
||||
|
||||
// Blink for Apple Silicon, e.g. M1 Macbook
|
||||
.ascii "if [ \"$s\" = Darwin ] && [ \"$m\" = arm64 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-darwin-arm64 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_darwin_arm64_b9
|
||||
.byte blink_darwin_arm64_b8
|
||||
.byte blink_darwin_arm64_b7
|
||||
.byte blink_darwin_arm64_b6
|
||||
.byte blink_darwin_arm64_b5
|
||||
.byte blink_darwin_arm64_b4
|
||||
.byte blink_darwin_arm64_b3
|
||||
.byte blink_darwin_arm64_b2
|
||||
.byte blink_darwin_arm64_b1
|
||||
.byte blink_darwin_arm64_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_darwin_arm64_size_b9
|
||||
.byte blink_darwin_arm64_size_b8
|
||||
.byte blink_darwin_arm64_size_b7
|
||||
.byte blink_darwin_arm64_size_b6
|
||||
.byte blink_darwin_arm64_size_b5
|
||||
.byte blink_darwin_arm64_size_b4
|
||||
.byte blink_darwin_arm64_size_b3
|
||||
.byte blink_darwin_arm64_size_b2
|
||||
.byte blink_darwin_arm64_size_b1
|
||||
.byte blink_darwin_arm64_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Aarch64 Linux, e.g. Raspberry Pi
|
||||
.ascii "if [ \"$s\" = Linux ]; then\n"
|
||||
.ascii "if [ \"$m\" = aarch64 ] || [ \"$m\" = arm64 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-aarch64 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_aarch64_b9
|
||||
.byte blink_aarch64_b8
|
||||
.byte blink_aarch64_b7
|
||||
.byte blink_aarch64_b6
|
||||
.byte blink_aarch64_b5
|
||||
.byte blink_aarch64_b4
|
||||
.byte blink_aarch64_b3
|
||||
.byte blink_aarch64_b2
|
||||
.byte blink_aarch64_b1
|
||||
.byte blink_aarch64_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_aarch64_size_b9
|
||||
.byte blink_aarch64_size_b8
|
||||
.byte blink_aarch64_size_b7
|
||||
.byte blink_aarch64_size_b6
|
||||
.byte blink_aarch64_size_b5
|
||||
.byte blink_aarch64_size_b4
|
||||
.byte blink_aarch64_size_b3
|
||||
.byte blink_aarch64_size_b2
|
||||
.byte blink_aarch64_size_b1
|
||||
.byte blink_aarch64_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux Generic ARM
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"${m#arm}\" != \"$m\" ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-arm to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_arm_b9
|
||||
.byte blink_arm_b8
|
||||
.byte blink_arm_b7
|
||||
.byte blink_arm_b6
|
||||
.byte blink_arm_b5
|
||||
.byte blink_arm_b4
|
||||
.byte blink_arm_b3
|
||||
.byte blink_arm_b2
|
||||
.byte blink_arm_b1
|
||||
.byte blink_arm_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_arm_size_b9
|
||||
.byte blink_arm_size_b8
|
||||
.byte blink_arm_size_b7
|
||||
.byte blink_arm_size_b6
|
||||
.byte blink_arm_size_b5
|
||||
.byte blink_arm_size_b4
|
||||
.byte blink_arm_size_b3
|
||||
.byte blink_arm_size_b2
|
||||
.byte blink_arm_size_b1
|
||||
.byte blink_arm_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on Legacy x86
|
||||
.ascii "if [ \"$s\" = Linux ]; then\n"
|
||||
.ascii "if [ \"$m\" = i686 ] || [ \"$m\" = i386 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-i486 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_i486_b9
|
||||
.byte blink_i486_b8
|
||||
.byte blink_i486_b7
|
||||
.byte blink_i486_b6
|
||||
.byte blink_i486_b5
|
||||
.byte blink_i486_b4
|
||||
.byte blink_i486_b3
|
||||
.byte blink_i486_b2
|
||||
.byte blink_i486_b1
|
||||
.byte blink_i486_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_i486_size_b9
|
||||
.byte blink_i486_size_b8
|
||||
.byte blink_i486_size_b7
|
||||
.byte blink_i486_size_b6
|
||||
.byte blink_i486_size_b5
|
||||
.byte blink_i486_size_b4
|
||||
.byte blink_i486_size_b3
|
||||
.byte blink_i486_size_b2
|
||||
.byte blink_i486_size_b1
|
||||
.byte blink_i486_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on RISC-V
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"$m\" = riscv64 ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-riscv64 to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_riscv64_b9
|
||||
.byte blink_riscv64_b8
|
||||
.byte blink_riscv64_b7
|
||||
.byte blink_riscv64_b6
|
||||
.byte blink_riscv64_b5
|
||||
.byte blink_riscv64_b4
|
||||
.byte blink_riscv64_b3
|
||||
.byte blink_riscv64_b2
|
||||
.byte blink_riscv64_b1
|
||||
.byte blink_riscv64_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_riscv64_size_b9
|
||||
.byte blink_riscv64_size_b8
|
||||
.byte blink_riscv64_size_b7
|
||||
.byte blink_riscv64_size_b6
|
||||
.byte blink_riscv64_size_b5
|
||||
.byte blink_riscv64_size_b4
|
||||
.byte blink_riscv64_size_b3
|
||||
.byte blink_riscv64_size_b2
|
||||
.byte blink_riscv64_size_b1
|
||||
.byte blink_riscv64_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on MIPS Little Endian, e.g. Ubiquiti EdgerouterX
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"$m\" = mips ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-mipsel to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_mipsel_b9
|
||||
.byte blink_mipsel_b8
|
||||
.byte blink_mipsel_b7
|
||||
.byte blink_mipsel_b6
|
||||
.byte blink_mipsel_b5
|
||||
.byte blink_mipsel_b4
|
||||
.byte blink_mipsel_b3
|
||||
.byte blink_mipsel_b2
|
||||
.byte blink_mipsel_b1
|
||||
.byte blink_mipsel_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_mipsel_size_b9
|
||||
.byte blink_mipsel_size_b8
|
||||
.byte blink_mipsel_size_b7
|
||||
.byte blink_mipsel_size_b6
|
||||
.byte blink_mipsel_size_b5
|
||||
.byte blink_mipsel_size_b4
|
||||
.byte blink_mipsel_size_b3
|
||||
.byte blink_mipsel_size_b2
|
||||
.byte blink_mipsel_size_b1
|
||||
.byte blink_mipsel_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on PowerPC 64 Little Endian, e.g. Raptor
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"$m\" = ppc64le ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-powerpc64le to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_powerpc64le_b9
|
||||
.byte blink_powerpc64le_b8
|
||||
.byte blink_powerpc64le_b7
|
||||
.byte blink_powerpc64le_b6
|
||||
.byte blink_powerpc64le_b5
|
||||
.byte blink_powerpc64le_b4
|
||||
.byte blink_powerpc64le_b3
|
||||
.byte blink_powerpc64le_b2
|
||||
.byte blink_powerpc64le_b1
|
||||
.byte blink_powerpc64le_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_powerpc64le_size_b9
|
||||
.byte blink_powerpc64le_size_b8
|
||||
.byte blink_powerpc64le_size_b7
|
||||
.byte blink_powerpc64le_size_b6
|
||||
.byte blink_powerpc64le_size_b5
|
||||
.byte blink_powerpc64le_size_b4
|
||||
.byte blink_powerpc64le_size_b3
|
||||
.byte blink_powerpc64le_size_b2
|
||||
.byte blink_powerpc64le_size_b1
|
||||
.byte blink_powerpc64le_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on PowerPC, e.g. Old Macintosh
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"$m\" = ppc ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-powerpc to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_powerpc_b9
|
||||
.byte blink_powerpc_b8
|
||||
.byte blink_powerpc_b7
|
||||
.byte blink_powerpc_b6
|
||||
.byte blink_powerpc_b5
|
||||
.byte blink_powerpc_b4
|
||||
.byte blink_powerpc_b3
|
||||
.byte blink_powerpc_b2
|
||||
.byte blink_powerpc_b1
|
||||
.byte blink_powerpc_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_powerpc_size_b9
|
||||
.byte blink_powerpc_size_b8
|
||||
.byte blink_powerpc_size_b7
|
||||
.byte blink_powerpc_size_b6
|
||||
.byte blink_powerpc_size_b5
|
||||
.byte blink_powerpc_size_b4
|
||||
.byte blink_powerpc_size_b3
|
||||
.byte blink_powerpc_size_b2
|
||||
.byte blink_powerpc_size_b1
|
||||
.byte blink_powerpc_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
// Blink for Linux on IBM Mainframes
|
||||
.ascii "if [ \"$s\" = Linux ] && [ \"$m\" = s390x ]; then\n"
|
||||
.ascii "if ! [ -x \"$e\" ]; then\n"
|
||||
.ascii "echo \"extracting blink-s390x to ${e}\" >&2\n"
|
||||
.ascii "dd if=\"$o\" bs=1 skip=$(("
|
||||
.byte blink_s390x_b9
|
||||
.byte blink_s390x_b8
|
||||
.byte blink_s390x_b7
|
||||
.byte blink_s390x_b6
|
||||
.byte blink_s390x_b5
|
||||
.byte blink_s390x_b4
|
||||
.byte blink_s390x_b3
|
||||
.byte blink_s390x_b2
|
||||
.byte blink_s390x_b1
|
||||
.byte blink_s390x_b0
|
||||
.ascii ")) count=$(("
|
||||
.byte blink_s390x_size_b9
|
||||
.byte blink_s390x_size_b8
|
||||
.byte blink_s390x_size_b7
|
||||
.byte blink_s390x_size_b6
|
||||
.byte blink_s390x_size_b5
|
||||
.byte blink_s390x_size_b4
|
||||
.byte blink_s390x_size_b3
|
||||
.byte blink_s390x_size_b2
|
||||
.byte blink_s390x_size_b1
|
||||
.byte blink_s390x_size_b0
|
||||
.ascii ")) conv=notrunc 2>/dev/null | gunzip >\"$e.$$\"\n"
|
||||
.ascii "mv -f \"$e.$$\" \"$e\"\n"
|
||||
.ascii "chmod +x \"$e\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$e\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
|
||||
.ascii "echo unsupported architecture >&2\n"
|
||||
.rept 16
|
||||
.ascii "exit 127\n"
|
||||
.endr
|
||||
|
||||
.ascii "exit 1\n"
|
||||
.endobj emush
|
||||
#ifdef APE_LOADER
|
||||
.section .ape.loader,"a",@progbits
|
||||
.align 64
|
||||
@@ -874,7 +1223,7 @@ ape_macho:
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad IMAGE_BASE_VIRTUAL # rbx
|
||||
.quad XNU # rcx
|
||||
.quad _HOSTXNU # rcx
|
||||
.quad 0 # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
@@ -1081,6 +1430,42 @@ ape_idata_idt:
|
||||
ape_idata_idtend:
|
||||
.previous
|
||||
|
||||
.section .piro.data.sort.metal_gdt,"aw",@progbits
|
||||
.align 8
|
||||
_gdt:
|
||||
// ┌G:granularity (1 → limit *= 0x1000)
|
||||
// │┌D/B:default operation size (0 = 16|64bit, 1 = 32-bit)
|
||||
// ││┌L:long mode
|
||||
// │││┌AVL:this bit is thine (1<<52)
|
||||
// ││││ ┌P:present
|
||||
// ││││ │┌DPL:privilege
|
||||
// ││││ ││ ┌─────────data/code(1)
|
||||
// ││││ ││ │┌────data(0)──────code(1)
|
||||
// ││││ ││ ││┌───conforming───expand-down
|
||||
// ││││ ││ │││┌──writeable────readable
|
||||
// ││││ ││ ││││┌─accessed─────accessed
|
||||
// ││││ ││ │││││
|
||||
// ││││ ┌──││─│││││───────────────────────────────┐
|
||||
// ┌───││││─│──││─│││││───────────┐ │
|
||||
// ┌───┴──┐││││┌┴─┐│├┐│││││┌──────────┴───────────┐┌──────┴───────┐
|
||||
// │ ││││││ ││││││││││ base address││ segment limit│
|
||||
// │ ││││││ ││││││││││ 32 bits││ 20 bits│
|
||||
// │ ││││││ ││││││││││ ││ │
|
||||
// 6666555555555544444444443333333333222222222211111111110000000000
|
||||
// 3210987654321098765432109876543210987654321098765432109876543210
|
||||
// │ ││││││ ││││││││││ ││ │
|
||||
.quad 0b0000000000000000000000000000000000000000000000000000000000000000 # 0
|
||||
.quad 0b0000000000001111100110100000000000000000000000001111111111111111 # 8
|
||||
.quad 0b0000000000001111100100100000000000000000000000001111111111111111 #16
|
||||
.quad 0b0000000011001111100110100000000000000000000000001111111111111111 #24
|
||||
.quad 0b0000000011001111100100100000000000000000000000001111111111111111 #32
|
||||
.quad 0b0000000010101111100110110000000000000000000000001111111111111111 #40
|
||||
.quad 0b0000000010101111100100110000000000000000000000001111111111111111 #48
|
||||
.tssdescstub _tss #56,64
|
||||
_gdt_end:
|
||||
.endobj _gdt,global,hidden
|
||||
.previous
|
||||
|
||||
.section .piro.data.sort.iat.1,"aw",@progbits
|
||||
.type ape_idata_iatend,@object
|
||||
.type ape_idata_iat,@object
|
||||
@@ -1137,42 +1522,22 @@ sconf: .short 1843200/*hz*/ / 16/*wut*/ / 9600/*baud*/
|
||||
.endobj sconf,global,hidden
|
||||
|
||||
// Global Descriptor Table
|
||||
//
|
||||
// @note address portion only concern legacy modes
|
||||
.align 8
|
||||
gdt: .short 2f-1f # table byte length
|
||||
.long REAL(1f),0 # table address
|
||||
.zero 2
|
||||
1:
|
||||
// ┌G:granularity (1 → limit *= 0x1000)
|
||||
// │┌D/B:default operation size (0 = 16|64bit, 1 = 32-bit)
|
||||
// ││┌L:long mode
|
||||
// │││┌AVL:this bit is thine (1<<52)
|
||||
// ││││ ┌P:present
|
||||
// ││││ │┌DPL:privilege
|
||||
// ││││ ││ ┌─────────data/code(1)
|
||||
// ││││ ││ │┌────data(0)──────code(1)
|
||||
// ││││ ││ ││┌───conforming───expand-down
|
||||
// ││││ ││ │││┌──writeable────readable
|
||||
// ││││ ││ ││││┌─accessed─────accessed
|
||||
// ││││ ││ │││││
|
||||
// ││││ ┌──││─│││││───────────────────────────────┐
|
||||
// ┌───││││─│──││─│││││───────────┐ │
|
||||
// ┌───┴──┐││││┌┴─┐│├┐│││││┌──────────┴───────────┐┌──────┴───────┐
|
||||
// │ ││││││ ││││││││││ base address││ segment limit│
|
||||
// │ ││││││ ││││││││││ 32 bits││ 20 bits│
|
||||
// │ ││││││ ││││││││││ ││ │
|
||||
// 6666555555555544444444443333333333222222222211111111110000000000
|
||||
// 3210987654321098765432109876543210987654321098765432109876543210
|
||||
// │ ││││││ ││││││││││ ││ │
|
||||
.quad 0b0000000000000000000000000000000000000000000000000000000000000000 # 0
|
||||
.quad 0b0000000000001111100110100000000000000000000000001111111111111111 # 8
|
||||
.quad 0b0000000000001111100100100000000000000000000000001111111111111111 #16
|
||||
.quad 0b0000000011001111100110100000000000000000000000001111111111111111 #24
|
||||
_gdtrlo:
|
||||
.short 2f-_gdtlo-1 # table byte length
|
||||
.long REAL(_gdtlo) # table address (base memory space)
|
||||
.endobj _gdtrlo,global,hidden
|
||||
_gdtr:
|
||||
.short _gdt_end-_gdt-1 # table byte length
|
||||
.quad _gdt # table address (final virtual space)
|
||||
.endobj _gdtr,global,hidden
|
||||
.align 8
|
||||
// Partial GDT with descriptors for switching to unreal mode or long mode.
|
||||
_gdtlo = .-GDT_LEGACY_DATA
|
||||
.quad 0b0000000011001111100100100000000000000000000000001111111111111111 #32
|
||||
.quad 0b0000000010101111100110110000000000000000000000001111111111111111 #40
|
||||
.quad 0b0000000010101111100100110000000000000000000000001111111111111111 #48
|
||||
2: .endobj gdt,global,hidden
|
||||
2:
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § real mode │
|
||||
@@ -1180,6 +1545,7 @@ gdt: .short 2f-1f # table byte length
|
||||
the default mode of operation on modern cpus */
|
||||
|
||||
realmodeloader:
|
||||
call lhinit
|
||||
call rlinit
|
||||
call sinit4
|
||||
.optfn _start16
|
||||
@@ -1187,6 +1553,25 @@ realmodeloader:
|
||||
call longmodeloader
|
||||
.endfn realmodeloader
|
||||
|
||||
// Prepares to later load parts of the program that are not loaded yet.
|
||||
//
|
||||
// @param al next sector number
|
||||
// @param cx next cylinder number
|
||||
// @param dh next head number
|
||||
// @param dl drive number
|
||||
// @clob ax, cx, es, di
|
||||
lhinit: cmp $0x40,%dl
|
||||
je 9f
|
||||
pushpop 0,%es
|
||||
mov $mm+"struct mman::pc_drive_next_sector",%di
|
||||
cld
|
||||
stosb #→ pc_drive_next_sector
|
||||
xchg %ax,%cx
|
||||
stosw #→ pc_drive_next_cylinder
|
||||
mov %dh,%al
|
||||
stosb #→ pc_drive_next_head
|
||||
9: ret
|
||||
|
||||
.section .sort.text.real.init.1,"ax",@progbits
|
||||
.type rlinit,@function
|
||||
rlinit: .previous/*
|
||||
@@ -1247,6 +1632,8 @@ longmodeloader:
|
||||
call lcheck
|
||||
call a20
|
||||
call e820
|
||||
call cpyhi
|
||||
call loadhi
|
||||
call pinit
|
||||
call golong
|
||||
.endfn longmodeloader
|
||||
@@ -1278,8 +1665,8 @@ lcheck: pushf # check for i8086 / i8088 / i80186
|
||||
jl 10f
|
||||
mov %edi,%eax
|
||||
cpuid
|
||||
mov $1<<29,%edi # need nexgen32e long mode support
|
||||
and %edi,%edx
|
||||
mov $1<<29|1<<20,%edi # need nexgen32e long mode support
|
||||
and %edi,%edx # & nx support
|
||||
cmp %edi,%edx
|
||||
jne 10f
|
||||
xor %ax,%ax
|
||||
@@ -1289,29 +1676,39 @@ lcheck: pushf # check for i8086 / i8088 / i80186
|
||||
.endfn lcheck
|
||||
|
||||
// Gets memory map from BIOS.
|
||||
e820: mov $0x0510>>4,%di # mman::e820
|
||||
mov %di,%es
|
||||
xor %edi,%edi # es:di is destination buffer
|
||||
xor %ebx,%ebx # ebx is an api state tracker
|
||||
e820: xor %ebx,%ebx # %ebx is an api state tracker
|
||||
mov %bx,%es
|
||||
mov $mm+"struct mman::e820",%di # es:di is destination buffer
|
||||
1: mov $0xE820,%eax # magic
|
||||
mov $8+8+4+4,%ecx # sizeof(struct SmapEntry)
|
||||
mov $0x534d4150,%edx # magic number
|
||||
movl $1,8+8+4/*SmapEntry::acpi3*/(%di) # prefill ACPI attributes;
|
||||
# apparently some buggy BIOSes say
|
||||
# that they return this field, yet
|
||||
# do not fill it correctly
|
||||
int $0x15 # ax,bx,cx,dx,di → ax,bx,cx
|
||||
jc 9f # cf = unsupported or abuse
|
||||
cmp %edx,%eax # more magic means success
|
||||
jne 9f
|
||||
test %cx,%cx # discard empty results
|
||||
jz 5f
|
||||
mov 8/*LODWORD(SmapEntry::size)*/(%di),%eax
|
||||
or 8+4/*HIDWORD(SmapEntry::size)*/(%di),%eax
|
||||
jz 5f
|
||||
cmp $8+8+4+1,%cx # discard if ignore flag
|
||||
jb 4f
|
||||
testb $1/*ignore*/,8+8+4/*SmapEntry::__acpi3*/(%di)
|
||||
jnz 5f
|
||||
testb $1/*don't ignore*/,8+8+4/*SmapEntry::acpi3*/(%di)
|
||||
jz 5f
|
||||
4: add $8+8+4+4,%di # keep entry
|
||||
5: test %ebx,%ebx # last entry?
|
||||
jz 8f
|
||||
cmp $0x1000,%di
|
||||
cmp $mm+"struct mman::e820_end"-(8+8+4+4),%di
|
||||
jb 1b
|
||||
8: ret
|
||||
8: xor %ax,%ax # add a blank sentinel entry
|
||||
mov $(8+8)/2,%cx
|
||||
cld
|
||||
rep stosw
|
||||
ret
|
||||
9: mov $REAL(str.e820),%di
|
||||
call rldie
|
||||
.endfn e820
|
||||
@@ -1379,11 +1776,96 @@ a20: cli
|
||||
5: ret
|
||||
.endfn a20
|
||||
|
||||
// Copies program pages loaded into base memory, to extended memory.
|
||||
//
|
||||
// @clob esi, edi
|
||||
cpyhi: push %es
|
||||
movpp %ds,%es
|
||||
call unreal
|
||||
mov $IMAGE_BASE_REAL,%esi
|
||||
mov $IMAGE_BASE_PHYSICAL,%edi
|
||||
mov $v_ape_realdwords,%ecx
|
||||
cld
|
||||
rep movsl %ds:(%esi),%es:(%edi)
|
||||
sti
|
||||
pop %es
|
||||
ret
|
||||
.endfn cpyhi
|
||||
|
||||
// Disables interrupts and switches to "unreal mode".
|
||||
//
|
||||
// @return ds, es have same base addresses as before but can access
|
||||
// 4 GiB of memory
|
||||
// @clob eax
|
||||
unreal: push %ds
|
||||
push %es
|
||||
cli
|
||||
lgdt REAL(_gdtrlo)
|
||||
mov %cr0,%eax
|
||||
or $CR0_PE,%al
|
||||
mov %eax,%cr0
|
||||
jmp 0f
|
||||
0: pushpop GDT_LEGACY_DATA,%ds
|
||||
movpp %ds,%es
|
||||
and $~CR0_PE,%al
|
||||
mov %eax,%cr0
|
||||
jmp 1f
|
||||
1: pop %es
|
||||
pop %ds
|
||||
ret
|
||||
|
||||
// Reads any remaining program pages into memory which have not yet
|
||||
// been read by the boot sector.
|
||||
//
|
||||
// @clob eax, ecx, dx, esi, edi, bp
|
||||
loadhi: mov $v_ape_highsectors,%bp
|
||||
test %bp,%bp
|
||||
jz 9f
|
||||
mov $mm+"struct mman::pc_drive",%si
|
||||
cld
|
||||
lodsb #← pc_drive
|
||||
xchg %ax,%dx
|
||||
lodsw
|
||||
lodsb #← pc_drive_next_sector
|
||||
test %al,%al
|
||||
jz 9f
|
||||
xchg %ax,%cx
|
||||
lodsw #← pc_drive_next_cylinder
|
||||
xchg %ax,%cx
|
||||
mov (%si),%dh #← pc_drive_next_head
|
||||
push %es
|
||||
#define SEG 0x79000
|
||||
mov $IMAGE_BASE_PHYSICAL+v_ape_realbytes-SEG,%edi
|
||||
push $SEG>>4
|
||||
pop %es
|
||||
0: call pcread
|
||||
push %ax
|
||||
call unreal
|
||||
pop %ax
|
||||
push %cx
|
||||
xor %esi,%esi
|
||||
xor %ecx,%ecx
|
||||
mov $512/4,%cl
|
||||
cld
|
||||
rep movsl %es:(%esi),%es:(%edi)
|
||||
sti
|
||||
pop %cx
|
||||
dec %bp
|
||||
jnz 0b
|
||||
pop %es
|
||||
9: ret
|
||||
|
||||
// Initializes long mode paging.
|
||||
pinit: push %ds
|
||||
#define SEG 0x79000
|
||||
push %es
|
||||
mov $SEG>>4,%ax
|
||||
mov %ax,%ds
|
||||
mov %ax,%es
|
||||
xor %di,%di
|
||||
xor %ax,%ax
|
||||
mov $(0x7f000-SEG)/2,%cx
|
||||
cld
|
||||
rep stosw
|
||||
movl $0x7d000+PAGE_V+PAGE_RW,0x7e000-SEG # PDPT←PML4T (+)
|
||||
movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPT←PML4T (-)
|
||||
movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDT←PDPT (+)
|
||||
@@ -1391,14 +1873,15 @@ pinit: push %ds
|
||||
movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+)
|
||||
movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-)
|
||||
mov $512,%cx # PD±2MB
|
||||
mov $PAGE_V+PAGE_RW,%eax
|
||||
xor %si,%si
|
||||
0: mov %eax,(%si)
|
||||
mov $PAGE_V+PAGE_RSRV+PAGE_RW,%eax
|
||||
xor %di,%di
|
||||
0: stosl
|
||||
add $0x1000,%eax
|
||||
add $8,%si
|
||||
scasl # di += 4
|
||||
loop 0b
|
||||
mov $0x7e000,%eax # PML4T←CR3
|
||||
mov %eax,%cr3
|
||||
pop %es
|
||||
pop %ds
|
||||
ret
|
||||
.endfn pinit
|
||||
@@ -1407,15 +1890,15 @@ pinit: push %ds
|
||||
//
|
||||
// @see Intel Manual V3A §4.1.2
|
||||
golong: cli
|
||||
lidt 0x1522 # mman::bad_idt
|
||||
lidt mm+"struct mman::bad_idt"
|
||||
mov %cr4,%eax
|
||||
or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax
|
||||
mov %eax,%cr4
|
||||
movl $EFER,%ecx
|
||||
rdmsr
|
||||
or $EFER_LME|EFER_SCE,%eax
|
||||
or $EFER_LME|EFER_SCE|EFER_NXE,%eax
|
||||
wrmsr
|
||||
lgdt REAL(gdt)
|
||||
lgdt REAL(_gdtrlo)
|
||||
mov %cr0,%eax
|
||||
or $CR0_PE|CR0_PG|CR0_MP,%eax
|
||||
and $~CR0_EM,%eax
|
||||
@@ -1425,7 +1908,9 @@ golong: cli
|
||||
|
||||
// Long mode is long.
|
||||
.code64
|
||||
long: xor %eax,%eax
|
||||
long: movabs $BANE+PHYSICAL(0f),%rax
|
||||
jmp *%rax
|
||||
0: xor %eax,%eax
|
||||
mov $GDT_LONG_DATA,%al
|
||||
mov %eax,%ds
|
||||
mov %eax,%ss
|
||||
@@ -1439,13 +1924,15 @@ long: xor %eax,%eax
|
||||
xor %r15d,%r15d
|
||||
xor %ebx,%ebx
|
||||
xor %ebp,%ebp
|
||||
push %rbp
|
||||
mov $0x0500,%rdi # mman
|
||||
mov $mm,%rdi
|
||||
mov %cr3,%rsi
|
||||
mov $IMAGE_BASE_REAL,%edx
|
||||
mov $IMAGE_BASE_PHYSICAL,%edx
|
||||
lea v_ape_allbytes(%rdx),%ecx
|
||||
call __map_phdrs
|
||||
push $0x037f
|
||||
fldcw (%rsp)
|
||||
lgdt _gdtr # reload GDTR for
|
||||
# virtual memory space
|
||||
movabs $kernel,%rax
|
||||
jmp *%rax
|
||||
.endfn long
|
||||
@@ -1526,21 +2013,25 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.byte 0x0f,0x1f,0207 # nop rdi binbase
|
||||
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
|
||||
#endif
|
||||
push $METAL # sets __hostos in crt.S
|
||||
movabs $BANE+mm,%rdi
|
||||
mov $0x79000,%esi
|
||||
mov $0x7f000,%edx
|
||||
call __reclaim_boot_pages
|
||||
push $_HOSTMETAL # sets __hostos in crt.S
|
||||
pop %rcx
|
||||
push $0
|
||||
pushq .Lenv0(%rip) # envp[0][0]
|
||||
mov %rsp,%rbp
|
||||
mov .Lenv0(%rip),%rax
|
||||
mov %rax,(%rbp) # envp[0][0]
|
||||
push $0 # argv[0][0]
|
||||
pushq .Largv0+8(%rip) # argv[0][8]
|
||||
pushq .Largv0(%rip) # argv[0][0]
|
||||
mov %rsp,%rax
|
||||
push $0 # auxv[1][1]
|
||||
push $0 # auxv[1][0]
|
||||
push %rbp # auxv[0][1]
|
||||
push %rax # auxv[0][1]
|
||||
push $31 # auxv[0][0] AT_EXECFN
|
||||
push $0 # envp[1]
|
||||
push $.Lenv0 # envp[0]
|
||||
push %rbp # envp[0]
|
||||
push $0 # argv[1]
|
||||
push %rbp # argv[0]
|
||||
push %rax # argv[0]
|
||||
push $1 # argc
|
||||
xor %ebp,%ebp
|
||||
xor %eax,%eax
|
||||
@@ -1556,6 +2047,9 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
|
||||
.rodata
|
||||
.Lenv0: .asciz "METAL=1"
|
||||
.Largv0:
|
||||
.asciz APE_COM_NAME
|
||||
.org .Largv0+16
|
||||
.previous
|
||||
|
||||
#endif /* SupportsMetal() */
|
||||
@@ -1568,7 +2062,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.ldsvar _end
|
||||
.ldsvar _etext
|
||||
.ldsvar v_ape_realsectors
|
||||
.ldsvar v_ape_realslacksectors
|
||||
.ldsvar v_ape_realbytes
|
||||
.ldsvar v_ape_highsectors
|
||||
.ldsvar ape_idata_ro
|
||||
.ldsvar ape_pad_rodata
|
||||
@@ -1662,5 +2156,77 @@ __bss_start:
|
||||
__bss_end:
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_aarch64_size
|
||||
blink_aarch64:
|
||||
.incbin "ape/blink-aarch64.gz"
|
||||
.endobj blink_aarch64,globl
|
||||
blink_aarch64_size = . - blink_aarch64
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_darwin_arm64_size
|
||||
blink_darwin_arm64:
|
||||
.incbin "ape/blink-darwin-arm64.gz"
|
||||
.endobj blink_darwin_arm64,globl
|
||||
blink_darwin_arm64_size = . - blink_darwin_arm64
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_arm_size
|
||||
blink_arm:
|
||||
.incbin "ape/blink-arm.gz"
|
||||
.endobj blink_arm,globl
|
||||
blink_arm_size = . - blink_arm
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_i486_size
|
||||
blink_i486:
|
||||
.incbin "ape/blink-i486.gz"
|
||||
.endobj blink_i486,globl
|
||||
blink_i486_size = . - blink_i486
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_riscv64_size
|
||||
blink_riscv64:
|
||||
.incbin "ape/blink-riscv64.gz"
|
||||
.endobj blink_riscv64,globl
|
||||
blink_riscv64_size = . - blink_riscv64
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_mipsel_size
|
||||
blink_mipsel:
|
||||
.incbin "ape/blink-mipsel.gz"
|
||||
.endobj blink_mipsel,globl
|
||||
blink_mipsel_size = . - blink_mipsel
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_powerpc64le_size
|
||||
blink_powerpc64le:
|
||||
.incbin "ape/blink-powerpc64le.gz"
|
||||
.endobj blink_powerpc64le,globl
|
||||
blink_powerpc64le_size = . - blink_powerpc64le
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_powerpc_size
|
||||
blink_powerpc:
|
||||
.incbin "ape/blink-powerpc.gz"
|
||||
.endobj blink_powerpc,globl
|
||||
blink_powerpc_size = . - blink_powerpc
|
||||
.previous
|
||||
|
||||
.section .blink,"a",@progbits
|
||||
.globl blink_s390x_size
|
||||
blink_s390x:
|
||||
.incbin "ape/blink-s390x.gz"
|
||||
.endobj blink_s390x,globl
|
||||
blink_s390x_size = . - blink_s390x
|
||||
.previous
|
||||
|
||||
.end
|
||||
|
||||
+241
-37
@@ -216,6 +216,8 @@ SECTIONS {
|
||||
KEEP(*(.elf.phdrs))
|
||||
HIDDEN(ape_phdrs_end = .);
|
||||
|
||||
KEEP(*(.emush))
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(ape_note = .);
|
||||
@@ -273,6 +275,7 @@ SECTIONS {
|
||||
KEEP(*(.textwindowsprologue))
|
||||
*(.text.windows)
|
||||
KEEP(*(.textwindowsepilogue))
|
||||
KEEP(*(.blink))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
@@ -349,9 +352,30 @@ SECTIONS {
|
||||
HIDDEN(_etext = .);
|
||||
PROVIDE_HIDDEN(etext = .);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
/*END: Read Only Data */
|
||||
} :Rom
|
||||
|
||||
/* initialization image for thread-local storage, this is copied */
|
||||
/* out to actual TLS areas at runtime, so just make it read-only */
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls :Rom
|
||||
/*END: Read Only Data */
|
||||
|
||||
/* this only tells the linker about the layout of uninitialized */
|
||||
/* TLS data, and does not advance the linker's location counter */
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
. = ALIGN(TLS_ALIGNMENT);
|
||||
/* the %fs register is based on this location */
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
.data ALIGN(PAGESIZE) : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
@@ -385,26 +409,7 @@ SECTIONS {
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Ram
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls :Ram
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*BEGIN: bss memory void */
|
||||
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
. = ALIGN(TLS_ALIGNMENT);
|
||||
/* the %fs register is based on this location */
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
||||
@@ -427,7 +432,7 @@ SECTIONS {
|
||||
|
||||
KEEP(*(.bssepilogue))
|
||||
/*END: NT FORK COPYING */
|
||||
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
|
||||
. = ALIGN(PAGESIZE);
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
} :Bss
|
||||
@@ -458,6 +463,7 @@ SECTIONS {
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
@@ -466,6 +472,7 @@ SECTIONS {
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
@@ -507,7 +514,7 @@ HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
||||
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
@@ -531,16 +538,16 @@ HIDDEN(ape_note_align = __SIZEOF_POINTER__);
|
||||
HIDDEN(ape_text_offset = ape_rom_offset + LOADADDR(.text) - ape_rom_paddr);
|
||||
HIDDEN(ape_text_paddr = LOADADDR(.text));
|
||||
HIDDEN(ape_text_vaddr = ADDR(.text));
|
||||
HIDDEN(ape_text_filesz = SIZEOF(.text));
|
||||
HIDDEN(ape_text_memsz = SIZEOF(.text));
|
||||
HIDDEN(ape_text_filesz = SIZEOF(.text) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_text_memsz = SIZEOF(.text) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_text_align = PAGESIZE);
|
||||
HIDDEN(ape_text_rva = RVA(ape_text_vaddr));
|
||||
|
||||
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
|
||||
HIDDEN(ape_data_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_data_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_align = PAGESIZE);
|
||||
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
|
||||
|
||||
@@ -560,16 +567,213 @@ SHSTUB2(ape_loader_dd_count,
|
||||
? ROUNDUP(ape_loader_end - ape_loader, PAGESIZE) / 64
|
||||
: 0);
|
||||
|
||||
HIDDEN(blink_aarch64_b0 = RVA(blink_aarch64) % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b1 = RVA(blink_aarch64) < 10 ? 32 : RVA(blink_aarch64) / 10 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b2 = RVA(blink_aarch64) < 100 ? 32 : RVA(blink_aarch64) / 100 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b3 = RVA(blink_aarch64) < 1000 ? 32 : RVA(blink_aarch64) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b4 = RVA(blink_aarch64) < 10000 ? 32 : RVA(blink_aarch64) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b5 = RVA(blink_aarch64) < 100000 ? 32 : RVA(blink_aarch64) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b6 = RVA(blink_aarch64) < 1000000 ? 32 : RVA(blink_aarch64) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b7 = RVA(blink_aarch64) < 10000000 ? 32 : RVA(blink_aarch64) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b8 = RVA(blink_aarch64) < 100000000 ? 32 : RVA(blink_aarch64) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_b9 = RVA(blink_aarch64) < 1000000000 ? 32 : RVA(blink_aarch64) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_aarch64_size_b0 = blink_aarch64_size % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b1 = blink_aarch64_size < 10 ? 32 : blink_aarch64_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b2 = blink_aarch64_size < 100 ? 32 : blink_aarch64_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b3 = blink_aarch64_size < 1000 ? 32 : blink_aarch64_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b4 = blink_aarch64_size < 10000 ? 32 : blink_aarch64_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b5 = blink_aarch64_size < 100000 ? 32 : blink_aarch64_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b6 = blink_aarch64_size < 1000000 ? 32 : blink_aarch64_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b7 = blink_aarch64_size < 10000000 ? 32 : blink_aarch64_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b8 = blink_aarch64_size < 100000000 ? 32 : blink_aarch64_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_aarch64_size_b9 = blink_aarch64_size < 1000000000 ? 32 : blink_aarch64_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_darwin_arm64_b0 = RVA(blink_darwin_arm64) % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b1 = RVA(blink_darwin_arm64) < 10 ? 32 : RVA(blink_darwin_arm64) / 10 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b2 = RVA(blink_darwin_arm64) < 100 ? 32 : RVA(blink_darwin_arm64) / 100 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b3 = RVA(blink_darwin_arm64) < 1000 ? 32 : RVA(blink_darwin_arm64) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b4 = RVA(blink_darwin_arm64) < 10000 ? 32 : RVA(blink_darwin_arm64) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b5 = RVA(blink_darwin_arm64) < 100000 ? 32 : RVA(blink_darwin_arm64) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b6 = RVA(blink_darwin_arm64) < 1000000 ? 32 : RVA(blink_darwin_arm64) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b7 = RVA(blink_darwin_arm64) < 10000000 ? 32 : RVA(blink_darwin_arm64) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b8 = RVA(blink_darwin_arm64) < 100000000 ? 32 : RVA(blink_darwin_arm64) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_b9 = RVA(blink_darwin_arm64) < 1000000000 ? 32 : RVA(blink_darwin_arm64) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_darwin_arm64_size_b0 = blink_darwin_arm64_size % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b1 = blink_darwin_arm64_size < 10 ? 32 : blink_darwin_arm64_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b2 = blink_darwin_arm64_size < 100 ? 32 : blink_darwin_arm64_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b3 = blink_darwin_arm64_size < 1000 ? 32 : blink_darwin_arm64_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b4 = blink_darwin_arm64_size < 10000 ? 32 : blink_darwin_arm64_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b5 = blink_darwin_arm64_size < 100000 ? 32 : blink_darwin_arm64_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b6 = blink_darwin_arm64_size < 1000000 ? 32 : blink_darwin_arm64_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b7 = blink_darwin_arm64_size < 10000000 ? 32 : blink_darwin_arm64_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b8 = blink_darwin_arm64_size < 100000000 ? 32 : blink_darwin_arm64_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_darwin_arm64_size_b9 = blink_darwin_arm64_size < 1000000000 ? 32 : blink_darwin_arm64_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_arm_b0 = RVA(blink_arm) % 10 + 48);
|
||||
HIDDEN(blink_arm_b1 = RVA(blink_arm) < 10 ? 32 : RVA(blink_arm) / 10 % 10 + 48);
|
||||
HIDDEN(blink_arm_b2 = RVA(blink_arm) < 100 ? 32 : RVA(blink_arm) / 100 % 10 + 48);
|
||||
HIDDEN(blink_arm_b3 = RVA(blink_arm) < 1000 ? 32 : RVA(blink_arm) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b4 = RVA(blink_arm) < 10000 ? 32 : RVA(blink_arm) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b5 = RVA(blink_arm) < 100000 ? 32 : RVA(blink_arm) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b6 = RVA(blink_arm) < 1000000 ? 32 : RVA(blink_arm) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b7 = RVA(blink_arm) < 10000000 ? 32 : RVA(blink_arm) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b8 = RVA(blink_arm) < 100000000 ? 32 : RVA(blink_arm) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_b9 = RVA(blink_arm) < 1000000000 ? 32 : RVA(blink_arm) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_arm_size_b0 = blink_arm_size % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b1 = blink_arm_size < 10 ? 32 : blink_arm_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b2 = blink_arm_size < 100 ? 32 : blink_arm_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b3 = blink_arm_size < 1000 ? 32 : blink_arm_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b4 = blink_arm_size < 10000 ? 32 : blink_arm_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b5 = blink_arm_size < 100000 ? 32 : blink_arm_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b6 = blink_arm_size < 1000000 ? 32 : blink_arm_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b7 = blink_arm_size < 10000000 ? 32 : blink_arm_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b8 = blink_arm_size < 100000000 ? 32 : blink_arm_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_arm_size_b9 = blink_arm_size < 1000000000 ? 32 : blink_arm_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_i486_b0 = RVA(blink_i486) % 10 + 48);
|
||||
HIDDEN(blink_i486_b1 = RVA(blink_i486) < 10 ? 32 : RVA(blink_i486) / 10 % 10 + 48);
|
||||
HIDDEN(blink_i486_b2 = RVA(blink_i486) < 100 ? 32 : RVA(blink_i486) / 100 % 10 + 48);
|
||||
HIDDEN(blink_i486_b3 = RVA(blink_i486) < 1000 ? 32 : RVA(blink_i486) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b4 = RVA(blink_i486) < 10000 ? 32 : RVA(blink_i486) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b5 = RVA(blink_i486) < 100000 ? 32 : RVA(blink_i486) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b6 = RVA(blink_i486) < 1000000 ? 32 : RVA(blink_i486) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b7 = RVA(blink_i486) < 10000000 ? 32 : RVA(blink_i486) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b8 = RVA(blink_i486) < 100000000 ? 32 : RVA(blink_i486) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_b9 = RVA(blink_i486) < 1000000000 ? 32 : RVA(blink_i486) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_i486_size_b0 = blink_i486_size % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b1 = blink_i486_size < 10 ? 32 : blink_i486_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b2 = blink_i486_size < 100 ? 32 : blink_i486_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b3 = blink_i486_size < 1000 ? 32 : blink_i486_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b4 = blink_i486_size < 10000 ? 32 : blink_i486_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b5 = blink_i486_size < 100000 ? 32 : blink_i486_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b6 = blink_i486_size < 1000000 ? 32 : blink_i486_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b7 = blink_i486_size < 10000000 ? 32 : blink_i486_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b8 = blink_i486_size < 100000000 ? 32 : blink_i486_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_i486_size_b9 = blink_i486_size < 1000000000 ? 32 : blink_i486_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_riscv64_b0 = RVA(blink_riscv64) % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b1 = RVA(blink_riscv64) < 10 ? 32 : RVA(blink_riscv64) / 10 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b2 = RVA(blink_riscv64) < 100 ? 32 : RVA(blink_riscv64) / 100 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b3 = RVA(blink_riscv64) < 1000 ? 32 : RVA(blink_riscv64) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b4 = RVA(blink_riscv64) < 10000 ? 32 : RVA(blink_riscv64) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b5 = RVA(blink_riscv64) < 100000 ? 32 : RVA(blink_riscv64) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b6 = RVA(blink_riscv64) < 1000000 ? 32 : RVA(blink_riscv64) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b7 = RVA(blink_riscv64) < 10000000 ? 32 : RVA(blink_riscv64) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b8 = RVA(blink_riscv64) < 100000000 ? 32 : RVA(blink_riscv64) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_b9 = RVA(blink_riscv64) < 1000000000 ? 32 : RVA(blink_riscv64) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_riscv64_size_b0 = blink_riscv64_size % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b1 = blink_riscv64_size < 10 ? 32 : blink_riscv64_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b2 = blink_riscv64_size < 100 ? 32 : blink_riscv64_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b3 = blink_riscv64_size < 1000 ? 32 : blink_riscv64_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b4 = blink_riscv64_size < 10000 ? 32 : blink_riscv64_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b5 = blink_riscv64_size < 100000 ? 32 : blink_riscv64_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b6 = blink_riscv64_size < 1000000 ? 32 : blink_riscv64_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b7 = blink_riscv64_size < 10000000 ? 32 : blink_riscv64_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b8 = blink_riscv64_size < 100000000 ? 32 : blink_riscv64_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_riscv64_size_b9 = blink_riscv64_size < 1000000000 ? 32 : blink_riscv64_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_mipsel_b0 = RVA(blink_mipsel) % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b1 = RVA(blink_mipsel) < 10 ? 32 : RVA(blink_mipsel) / 10 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b2 = RVA(blink_mipsel) < 100 ? 32 : RVA(blink_mipsel) / 100 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b3 = RVA(blink_mipsel) < 1000 ? 32 : RVA(blink_mipsel) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b4 = RVA(blink_mipsel) < 10000 ? 32 : RVA(blink_mipsel) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b5 = RVA(blink_mipsel) < 100000 ? 32 : RVA(blink_mipsel) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b6 = RVA(blink_mipsel) < 1000000 ? 32 : RVA(blink_mipsel) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b7 = RVA(blink_mipsel) < 10000000 ? 32 : RVA(blink_mipsel) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b8 = RVA(blink_mipsel) < 100000000 ? 32 : RVA(blink_mipsel) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_b9 = RVA(blink_mipsel) < 1000000000 ? 32 : RVA(blink_mipsel) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_mipsel_size_b0 = blink_mipsel_size % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b1 = blink_mipsel_size < 10 ? 32 : blink_mipsel_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b2 = blink_mipsel_size < 100 ? 32 : blink_mipsel_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b3 = blink_mipsel_size < 1000 ? 32 : blink_mipsel_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b4 = blink_mipsel_size < 10000 ? 32 : blink_mipsel_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b5 = blink_mipsel_size < 100000 ? 32 : blink_mipsel_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b6 = blink_mipsel_size < 1000000 ? 32 : blink_mipsel_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b7 = blink_mipsel_size < 10000000 ? 32 : blink_mipsel_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b8 = blink_mipsel_size < 100000000 ? 32 : blink_mipsel_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_mipsel_size_b9 = blink_mipsel_size < 1000000000 ? 32 : blink_mipsel_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_powerpc64le_b0 = RVA(blink_powerpc64le) % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b1 = RVA(blink_powerpc64le) < 10 ? 32 : RVA(blink_powerpc64le) / 10 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b2 = RVA(blink_powerpc64le) < 100 ? 32 : RVA(blink_powerpc64le) / 100 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b3 = RVA(blink_powerpc64le) < 1000 ? 32 : RVA(blink_powerpc64le) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b4 = RVA(blink_powerpc64le) < 10000 ? 32 : RVA(blink_powerpc64le) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b5 = RVA(blink_powerpc64le) < 100000 ? 32 : RVA(blink_powerpc64le) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b6 = RVA(blink_powerpc64le) < 1000000 ? 32 : RVA(blink_powerpc64le) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b7 = RVA(blink_powerpc64le) < 10000000 ? 32 : RVA(blink_powerpc64le) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b8 = RVA(blink_powerpc64le) < 100000000 ? 32 : RVA(blink_powerpc64le) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_b9 = RVA(blink_powerpc64le) < 1000000000 ? 32 : RVA(blink_powerpc64le) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_powerpc64le_size_b0 = blink_powerpc64le_size % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b1 = blink_powerpc64le_size < 10 ? 32 : blink_powerpc64le_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b2 = blink_powerpc64le_size < 100 ? 32 : blink_powerpc64le_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b3 = blink_powerpc64le_size < 1000 ? 32 : blink_powerpc64le_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b4 = blink_powerpc64le_size < 10000 ? 32 : blink_powerpc64le_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b5 = blink_powerpc64le_size < 100000 ? 32 : blink_powerpc64le_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b6 = blink_powerpc64le_size < 1000000 ? 32 : blink_powerpc64le_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b7 = blink_powerpc64le_size < 10000000 ? 32 : blink_powerpc64le_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b8 = blink_powerpc64le_size < 100000000 ? 32 : blink_powerpc64le_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc64le_size_b9 = blink_powerpc64le_size < 1000000000 ? 32 : blink_powerpc64le_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_powerpc_b0 = RVA(blink_powerpc) % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b1 = RVA(blink_powerpc) < 10 ? 32 : RVA(blink_powerpc) / 10 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b2 = RVA(blink_powerpc) < 100 ? 32 : RVA(blink_powerpc) / 100 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b3 = RVA(blink_powerpc) < 1000 ? 32 : RVA(blink_powerpc) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b4 = RVA(blink_powerpc) < 10000 ? 32 : RVA(blink_powerpc) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b5 = RVA(blink_powerpc) < 100000 ? 32 : RVA(blink_powerpc) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b6 = RVA(blink_powerpc) < 1000000 ? 32 : RVA(blink_powerpc) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b7 = RVA(blink_powerpc) < 10000000 ? 32 : RVA(blink_powerpc) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b8 = RVA(blink_powerpc) < 100000000 ? 32 : RVA(blink_powerpc) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_b9 = RVA(blink_powerpc) < 1000000000 ? 32 : RVA(blink_powerpc) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_powerpc_size_b0 = blink_powerpc_size % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b1 = blink_powerpc_size < 10 ? 32 : blink_powerpc_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b2 = blink_powerpc_size < 100 ? 32 : blink_powerpc_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b3 = blink_powerpc_size < 1000 ? 32 : blink_powerpc_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b4 = blink_powerpc_size < 10000 ? 32 : blink_powerpc_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b5 = blink_powerpc_size < 100000 ? 32 : blink_powerpc_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b6 = blink_powerpc_size < 1000000 ? 32 : blink_powerpc_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b7 = blink_powerpc_size < 10000000 ? 32 : blink_powerpc_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b8 = blink_powerpc_size < 100000000 ? 32 : blink_powerpc_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_powerpc_size_b9 = blink_powerpc_size < 1000000000 ? 32 : blink_powerpc_size / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_s390x_b0 = RVA(blink_s390x) % 10 + 48);
|
||||
HIDDEN(blink_s390x_b1 = RVA(blink_s390x) < 10 ? 32 : RVA(blink_s390x) / 10 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b2 = RVA(blink_s390x) < 100 ? 32 : RVA(blink_s390x) / 100 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b3 = RVA(blink_s390x) < 1000 ? 32 : RVA(blink_s390x) / 1000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b4 = RVA(blink_s390x) < 10000 ? 32 : RVA(blink_s390x) / 10000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b5 = RVA(blink_s390x) < 100000 ? 32 : RVA(blink_s390x) / 100000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b6 = RVA(blink_s390x) < 1000000 ? 32 : RVA(blink_s390x) / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b7 = RVA(blink_s390x) < 10000000 ? 32 : RVA(blink_s390x) / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b8 = RVA(blink_s390x) < 100000000 ? 32 : RVA(blink_s390x) / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_b9 = RVA(blink_s390x) < 1000000000 ? 32 : RVA(blink_s390x) / 1000000000 % 10 + 48);
|
||||
|
||||
HIDDEN(blink_s390x_size_b0 = blink_s390x_size % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b1 = blink_s390x_size < 10 ? 32 : blink_s390x_size / 10 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b2 = blink_s390x_size < 100 ? 32 : blink_s390x_size / 100 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b3 = blink_s390x_size < 1000 ? 32 : blink_s390x_size / 1000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b4 = blink_s390x_size < 10000 ? 32 : blink_s390x_size / 10000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b5 = blink_s390x_size < 100000 ? 32 : blink_s390x_size / 100000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b6 = blink_s390x_size < 1000000 ? 32 : blink_s390x_size / 1000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b7 = blink_s390x_size < 10000000 ? 32 : blink_s390x_size / 10000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b8 = blink_s390x_size < 100000000 ? 32 : blink_s390x_size / 100000000 % 10 + 48);
|
||||
HIDDEN(blink_s390x_size_b9 = blink_s390x_size < 1000000000 ? 32 : blink_s390x_size / 1000000000 % 10 + 48);
|
||||
|
||||
#if SupportsMetal()
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(0x70000 - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 4096)) / 512);
|
||||
HIDDEN(v_ape_realslacksectors =
|
||||
v_ape_realsectors - MIN(0x70000 - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 512)) / 512);
|
||||
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
|
||||
HIDDEN(v_ape_highsectors =
|
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
|
||||
MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512);
|
||||
HIDDEN(v_ape_realbytes = v_ape_realsectors * 512);
|
||||
HIDDEN(v_ape_realdwords = v_ape_realsectors * (512 / 4));
|
||||
HIDDEN(v_ape_allsectors = ROUNDUP(RVA(_ezip), 512) / 512);
|
||||
HIDDEN(v_ape_allbytes = v_ape_allsectors * 512);
|
||||
HIDDEN(v_ape_highsectors = v_ape_allsectors - v_ape_realsectors);
|
||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||
#endif
|
||||
|
||||
/* ZIP End of Central Directory header */
|
||||
@@ -651,7 +855,7 @@ CHURN(ADDR(.bss));
|
||||
CHURN(_start);
|
||||
CHURN(ape_phdrs);
|
||||
#if SupportsMetal()
|
||||
CHURN(v_ape_realsectors);
|
||||
CHURN(v_ape_allsectors);
|
||||
#endif
|
||||
#if SupportsXnu()
|
||||
CHURN(ape_macho);
|
||||
@@ -714,8 +918,8 @@ ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||
ASSERT(IS2POW(ape_stack_memsz),
|
||||
"ape_stack_memsz must be a two power");
|
||||
|
||||
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
|
||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
|
||||
ASSERT(ape_stack_vaddr % ape_stack_memsz == 0,
|
||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000040000 & -ape_stack_memsz);");
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
|
||||
+34
-1
@@ -65,6 +65,7 @@ o/$(MODE)/ape/ape.lds: \
|
||||
libc/intrin/bits.h \
|
||||
libc/thread/tls.h \
|
||||
libc/calls/struct/timespec.h \
|
||||
libc/thread/thread.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/elf/pf2prot.internal.h \
|
||||
@@ -82,6 +83,7 @@ o/$(MODE)/ape/public/ape.lds: \
|
||||
libc/intrin/bits.h \
|
||||
libc/thread/tls.h \
|
||||
libc/calls/struct/timespec.h \
|
||||
libc/thread/thread.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/elf/pf2prot.internal.h \
|
||||
@@ -94,6 +96,17 @@ o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
ape/relocations.h
|
||||
|
||||
o/$(MODE)/ape/ape.o: \
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-arm.gz \
|
||||
ape/blink-darwin-arm64.gz \
|
||||
ape/blink-i486.gz \
|
||||
ape/blink-mipsel.gz \
|
||||
ape/blink-powerpc.gz \
|
||||
ape/blink-powerpc64le.gz \
|
||||
ape/blink-riscv64.gz \
|
||||
ape/blink-s390x.gz
|
||||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
ape/ape.S \
|
||||
ape/macros.internal.h \
|
||||
@@ -105,6 +118,7 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
libc/macho.internal.h \
|
||||
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 \
|
||||
@@ -112,6 +126,15 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-arm.gz \
|
||||
ape/blink-darwin-arm64.gz \
|
||||
ape/blink-i486.gz \
|
||||
ape/blink-mipsel.gz \
|
||||
ape/blink-powerpc.gz \
|
||||
ape/blink-powerpc64le.gz \
|
||||
ape/blink-riscv64.gz \
|
||||
ape/blink-s390x.gz \
|
||||
o/$(MODE)/ape/ape.elf
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
@@ -131,13 +154,23 @@ o/$(MODE)/ape/ape-copy-self.o: \
|
||||
libc/macho.internal.h \
|
||||
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/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h
|
||||
libc/sysv/consts/prot.h \
|
||||
ape/blink-aarch64.gz \
|
||||
ape/blink-arm.gz \
|
||||
ape/blink-darwin-arm64.gz \
|
||||
ape/blink-i486.gz \
|
||||
ape/blink-mipsel.gz \
|
||||
ape/blink-powerpc.gz \
|
||||
ape/blink-powerpc64le.gz \
|
||||
ape/blink-riscv64.gz \
|
||||
ape/blink-s390x.gz
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
$(OBJECTIFY.S) \
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $UID -eq 0 ]; then
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
SUDO=
|
||||
else
|
||||
SUDO=sudo
|
||||
@@ -97,6 +97,8 @@ if [ x"$(uname -s)" = xLinux ]; then
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
|
||||
+8
-6
@@ -8,17 +8,19 @@ fi
|
||||
|
||||
{
|
||||
echo
|
||||
echo "APE Uninstaller intends to run"
|
||||
echo "APE Uninstaller intends to run (in pseudo-shell)"
|
||||
echo
|
||||
echo " $SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE'"
|
||||
echo " $SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
|
||||
echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*"
|
||||
echo " sudo rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
|
||||
echo
|
||||
echo "You may then use ape/apeinstall.sh to reinstall it"
|
||||
echo
|
||||
} >&2
|
||||
|
||||
set -ex
|
||||
if [ -f /proc/sys/fs/binfmt_misc/APE ]; then
|
||||
$SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE' || exit
|
||||
fi
|
||||
for f in /proc/sys/fs/binfmt_misc/APE*; do
|
||||
if [ -f $f ]; then
|
||||
$SUDO sh -c "echo -1 >$f" || exit
|
||||
fi
|
||||
done
|
||||
$SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape o/tmp/ape /tmp/.ape /tmp/ape || exit
|
||||
Binary file not shown.
Binary file not shown.
File renamed without changes.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33
-33
@@ -32,23 +32,23 @@
|
||||
// @see ape/ape.lds
|
||||
// @see winimp
|
||||
.macro .imp dll:req fn:req actual:req hint
|
||||
.dll \dll
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
|
||||
.dll "\dll"
|
||||
.section ".piro.data.sort.iat.2.\dll\().2.\actual","aw",@progbits
|
||||
.type \fn,@object
|
||||
.align __SIZEOF_POINTER__
|
||||
\fn: .quad RVA((\dll\().\actual))
|
||||
\fn: .quad RVA(("\dll\().\actual"))
|
||||
.size \fn,.-\fn
|
||||
.globl \fn
|
||||
.hidden \fn
|
||||
.previous
|
||||
.section .idata.ro.ilt.\dll\().2.\actual,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\actual:
|
||||
.quad RVA((\dll\().\actual))
|
||||
.type .Lidata.ilt.\dll\().\actual,@object
|
||||
.size .Lidata.ilt.\dll\().\actual,.-.Lidata.ilt.\dll\().\actual
|
||||
.section ".idata.ro.ilt.\dll\().2.\actual","a",@progbits
|
||||
".Lidata.ilt.\dll\().\actual":
|
||||
.quad RVA("\dll\().\actual")
|
||||
.type ".Lidata.ilt.\dll\().\actual",@object
|
||||
.size ".Lidata.ilt.\dll\().\actual",.-".Lidata.ilt.\dll\().\actual"
|
||||
.previous
|
||||
.section .idata.ro.hnt.\dll\().2.\actual,"a",@progbits
|
||||
\dll\().\actual:
|
||||
.section ".idata.ro.hnt.\dll\().2.\actual","a",@progbits
|
||||
"\dll\().\actual":
|
||||
.ifnb \hint # hint i.e. guess function ordinal
|
||||
.short \hint
|
||||
.else
|
||||
@@ -56,55 +56,55 @@
|
||||
.endif
|
||||
.asciz "\actual"
|
||||
.align 2 # documented requirement
|
||||
.globl \dll\().\actual
|
||||
.hidden \dll\().\actual
|
||||
.type \dll\().\actual,@object
|
||||
.size \dll\().\actual,.-\dll\().\actual
|
||||
.globl "\dll\().\actual"
|
||||
.hidden "\dll\().\actual"
|
||||
.type "\dll\().\actual",@object
|
||||
.size "\dll\().\actual",.-"\dll\().\actual"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
// Defines DLL import.
|
||||
// @note this is an implementation detail of .imp
|
||||
.macro .dll name:req
|
||||
.section .idata.ro.idt.2.\name,"aG",@progbits,\name,comdat
|
||||
.equ .Lidata.idt.\name,.
|
||||
.long RVA(idata.ilt.\name) # ImportLookupTable
|
||||
.section ".idata.ro.idt.2.\name","aG",@progbits,"\name",comdat
|
||||
.equ ".Lidata.idt.\name",.
|
||||
.long RVA("idata.ilt.\name") # ImportLookupTable
|
||||
.long 0 # TimeDateStamp
|
||||
.long 0 # ForwarderChain
|
||||
.long RVA(.Lidata.str.\name) # DllNameRva
|
||||
.long RVA(idata.iat.\name) # ImportAddressTable
|
||||
.type .Lidata.idt.\name,@object
|
||||
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
||||
.long RVA(".Lidata.str.\name") # DllNameRva
|
||||
.long RVA("idata.iat.\name") # ImportAddressTable
|
||||
.type ".Lidata.idt.\name",@object
|
||||
.size ".Lidata.idt.\name",.-".Lidata.idt.\name"
|
||||
.previous
|
||||
.section .idata.ro.ilt.\name\().1,"aG",@progbits,\name,comdat
|
||||
.section ".idata.ro.ilt.\name\().1","aG",@progbits,"\name",comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.ilt.\name,@object
|
||||
idata.ilt.\name:
|
||||
.type "idata.ilt.\name",@object
|
||||
"idata.ilt.\name":
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .idata.ro.ilt.\name\().3,"aG",@progbits,\name,comdat
|
||||
*/.section ".idata.ro.ilt.\name\().3","aG",@progbits,"\name",comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section .idata.ro.hnt.\name\().1,"aG",@progbits,\name,comdat
|
||||
.section ".idata.ro.hnt.\name\().1","aG",@progbits,"\name",comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.hnt.\name,@object
|
||||
.equ idata.hnt.\name,.
|
||||
.type "idata.hnt.\name",@object
|
||||
.equ "idata.hnt.\name",.
|
||||
.previous
|
||||
.section .piro.data.sort.iat.2.\name\().1,"awG",@progbits,\name,comdat
|
||||
.section ".piro.data.sort.iat.2.\name\().1","awG",@progbits,"\name",comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.iat.\name,@object
|
||||
idata.iat.\name:
|
||||
.type "idata.iat.\name",@object
|
||||
"idata.iat.\name":
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section .piro.data.sort.iat.2.\name\().3,"awG",@progbits,\name,comdat
|
||||
*/.section ".piro.data.sort.iat.2.\name\().3","awG",@progbits,"\name",comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section .rodata.str1.1,"aSM",@progbits,1
|
||||
.Lidata.str.\name:
|
||||
".Lidata.str.\name":
|
||||
.asciz "\name\().dll"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
+2
-2
@@ -175,7 +175,7 @@ macho: .long 0xFEEDFACE+1
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad _HOSTXNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
@@ -221,7 +221,7 @@ _start:
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
mov $_HOSTXNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
|
||||
+2
-2
@@ -90,7 +90,7 @@ macho: .long 0xFEEDFACE+1
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad _HOSTXNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
@@ -121,7 +121,7 @@ _start:
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
mov $_HOSTXNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
|
||||
@@ -180,6 +180,20 @@
|
||||
.stub \name\()_bcs\n,long
|
||||
.endm
|
||||
|
||||
// Task State Segment Descriptor Entries.
|
||||
.macro .tssdescstub name:req
|
||||
.ifndef \name
|
||||
.weak \name
|
||||
.set \name,0
|
||||
.endif
|
||||
.ifndef \name\()_end
|
||||
.weak \name\()_end
|
||||
.set \name\()_end,0
|
||||
.endif
|
||||
.stub \name\()_desc_ent0,quad
|
||||
.stub \name\()_desc_ent1,quad
|
||||
.endm
|
||||
|
||||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
@@ -257,5 +271,22 @@
|
||||
(X) % 10 * 0x1000000 \
|
||||
: 0xffffffffffffffff)
|
||||
|
||||
/**
|
||||
* Laying out the GDT entries for a TSS for bare metal operation.
|
||||
*/
|
||||
#define TSSDESCSTUB2(SYM, BASE, LIM) \
|
||||
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
|
||||
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
||||
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
||||
#define TSSDESC_ENT0(BASE, LIM) \
|
||||
(((LIM) << 0 & 0x000000000000ffff) | \
|
||||
((BASE) << 16 & 0x000000ffffff0000) | \
|
||||
0x89 << 40 | \
|
||||
((LIM) >> 16 << 48 & 0x000f000000000000) | \
|
||||
0x2 << 52 | \
|
||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||
#define TSSDESC_ENT1(BASE) \
|
||||
((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
||||
+2
-2
@@ -36,8 +36,8 @@
|
||||
*/
|
||||
#define REAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_REAL))
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL % 0x200000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 2mb aligned"
|
||||
#if IMAGE_BASE_VIRTUAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 4kb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_PHYSICAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_PHYSICAL must be 4kb aligned"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern unsigned char _base[];
|
||||
extern unsigned char _ehead[];
|
||||
extern unsigned char _etext[];
|
||||
extern unsigned char _edata[];
|
||||
extern unsigned char _ezip[];
|
||||
extern unsigned char _end[];
|
||||
extern unsigned char _ereal[];
|
||||
extern unsigned char _tdata_start[];
|
||||
extern unsigned char _tdata_end[];
|
||||
extern unsigned char _tbss_start[];
|
||||
extern unsigned char _tbss_end[];
|
||||
extern unsigned char __privileged_start[];
|
||||
extern unsigned char __privileged_addr[];
|
||||
extern unsigned char __privileged_size[];
|
||||
extern unsigned char __privileged_end[];
|
||||
extern unsigned char __test_start[];
|
||||
extern unsigned char __ro[];
|
||||
extern unsigned char *__relo_start[];
|
||||
extern unsigned char *__relo_end[];
|
||||
extern uint8_t __zip_start[];
|
||||
extern uint8_t __zip_end[];
|
||||
extern uint8_t __data_start[];
|
||||
extern uint8_t __data_end[];
|
||||
extern uint8_t __bss_start[];
|
||||
extern uint8_t __bss_end[];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+70
-7
@@ -29,7 +29,7 @@ endif
|
||||
#
|
||||
ifeq ($(MODE),fastbuild)
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
|
||||
CONFIG_OFLAGS += -g0
|
||||
CONFIG_LDFLAGS += -S
|
||||
TARGET_ARCH ?= -msse3
|
||||
@@ -102,7 +102,7 @@ endif
|
||||
# - Larger binaries
|
||||
#
|
||||
ifeq ($(MODE), asan)
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=address
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
@@ -125,6 +125,22 @@ TARGET_ARCH ?= -msse3
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
endif
|
||||
|
||||
# System Five Mode
|
||||
#
|
||||
# - `make MODE=sysv`
|
||||
# - Optimized
|
||||
# - Backtraces
|
||||
# - Debuggable
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - No Windows bloat!
|
||||
#
|
||||
ifeq ($(MODE), sysv)
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
|
||||
# Tiny Mode
|
||||
#
|
||||
# - `make MODE=tiny`
|
||||
@@ -151,7 +167,12 @@ CONFIG_CCFLAGS += \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
@@ -177,9 +198,14 @@ CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=1
|
||||
-DSUPPORT_VECTOR=1 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -209,9 +235,14 @@ CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=113
|
||||
-DSUPPORT_VECTOR=113 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -240,7 +271,8 @@ CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=121
|
||||
-DSUPPORT_VECTOR=121 \
|
||||
-DDWARFLESS
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
@@ -249,6 +281,10 @@ CONFIG_CCFLAGS += \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
@@ -271,17 +307,44 @@ CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=251
|
||||
-DSUPPORT_VECTOR=251 \
|
||||
-DDWARFLESS
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
CONFIG_OFLAGS += \
|
||||
-g0
|
||||
CONFIG_LDFLAGS += \
|
||||
-S
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# GCC11 Mode
|
||||
# https://justine.lol/compilers/x86_64-linux-musl__x86_64-linux-musl__g++-11.2.0.tar.xz
|
||||
ifeq ($(MODE), gcc11)
|
||||
.UNVEIL += rx:/opt/gcc11
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
|
||||
AS = /opt/gcc11/bin/x86_64-linux-musl-as
|
||||
CC = /opt/gcc11/bin/x86_64-linux-musl-gcc
|
||||
CXX = /opt/gcc11/bin/x86_64-linux-musl-g++
|
||||
CXXFILT = /opt/gcc11/bin/x86_64-linux-musl-c++filt
|
||||
LD = /opt/gcc11/bin/x86_64-linux-musl-ld.bfd
|
||||
NM = /opt/gcc11/bin/x86_64-linux-musl-nm
|
||||
GCC = /opt/gcc11/bin/x86_64-linux-musl-gcc
|
||||
STRIP = /opt/gcc11/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = /opt/gcc11/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = /opt/gcc11/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = /opt/gcc11/bin/x86_64-linux-musl-addr2line
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2 -Wno-stringop-overread
|
||||
CONFIG_CFLAGS += -Wno-old-style-definition
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||
TARGET_ARCH ?= -msse3
|
||||
endif
|
||||
|
||||
# LLVM Mode
|
||||
ifeq ($(MODE), llvm)
|
||||
TARGET_ARCH ?= -msse3
|
||||
|
||||
+16
-24
@@ -45,7 +45,6 @@
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
|
||||
TAGS ?= /usr/bin/ctags # emacs source builds or something breaks it
|
||||
ARFLAGS = rcsD
|
||||
ZFLAGS ?=
|
||||
XARGS ?= xargs -P4 -rs8000
|
||||
@@ -73,33 +72,25 @@ IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
IGNORE := $(shell $(ECHO) -2 ♥cosmo)
|
||||
IGNORE := $(shell $(MKDIR) o/tmp)
|
||||
|
||||
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe)","")
|
||||
AS = o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe
|
||||
CC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
CXX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-g++.exe
|
||||
CXXFILT = o/third_party/gcc/bin/x86_64-pc-linux-gnu-c++filt.exe
|
||||
LD = o/third_party/gcc/bin/x86_64-pc-linux-gnu-ld.bfd.exe
|
||||
NM = o/third_party/gcc/bin/x86_64-pc-linux-gnu-nm.exe
|
||||
GCC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
STRIP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-strip.exe
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objcopy.exe
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objdump.exe
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-pc-linux-gnu-addr2line.exe
|
||||
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","")
|
||||
PREFIX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-
|
||||
else
|
||||
IGNORE := $(shell build/bootstrap/unbundle.com)
|
||||
AS = o/third_party/gcc/bin/x86_64-linux-musl-as
|
||||
CC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++
|
||||
CXXFILT = o/third_party/gcc/bin/x86_64-linux-musl-c++filt
|
||||
LD = o/third_party/gcc/bin/x86_64-linux-musl-ld.bfd
|
||||
NM = o/third_party/gcc/bin/x86_64-linux-musl-nm
|
||||
GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
PREFIX = o/third_party/gcc/bin/x86_64-linux-musl-
|
||||
endif
|
||||
|
||||
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
|
||||
ADDR2LINE = $(PWD)/$(PREFIX)addr2line
|
||||
|
||||
export ADDR2LINE
|
||||
export LC_ALL
|
||||
export MKDIR
|
||||
@@ -148,6 +139,7 @@ DEFAULT_CCFLAGS = \
|
||||
|
||||
DEFAULT_OFLAGS = \
|
||||
-g \
|
||||
-gdwarf-4 \
|
||||
-gdescribe-dies
|
||||
|
||||
DEFAULT_COPTS = \
|
||||
|
||||
+4
-1
@@ -43,6 +43,9 @@
|
||||
# '(progn
|
||||
# (add-hook 'c-mode-common-hook 'jart-c-mode-common-hook)))
|
||||
|
||||
TAGS="$1"
|
||||
shift
|
||||
|
||||
# ctags doesn't understand atomics, e.g.
|
||||
# extern char **environ;
|
||||
set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
|
||||
@@ -63,7 +66,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
|
||||
# struct WorstSoftwareEver;
|
||||
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
|
||||
|
||||
exec ${TAGS:-ctags} \
|
||||
exec $TAGS \
|
||||
-e \
|
||||
--langmap=c:.c.h \
|
||||
--exclude=libc/nt/struct/imagefileheader.internal.h \
|
||||
|
||||
+8
-8
@@ -163,15 +163,15 @@ o/$(MODE)%/.zip.o: %
|
||||
# and it would be too costly in terms of make latency to have every
|
||||
# header file depend on $(HDRS) and $(INCS).
|
||||
|
||||
o/%.h.ok: .UNSANDBOXED = 1
|
||||
o/%.h.ok: private .UNSANDBOXED = 1
|
||||
o/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.h.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.h.ok: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.hh.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.hh.ok: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.hh.ok: %.hh
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
@@ -179,7 +179,7 @@ o/%.okk: .UNSANDBOXED = 1
|
||||
o/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.okk: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.okk: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
@@ -207,19 +207,19 @@ MAKE_SYMTAB_ZIP = \
|
||||
################################################################################
|
||||
# EMACS ASSEMBLY GENERATION
|
||||
|
||||
o/$(MODE)/%-gcc.asm: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-gcc.asm: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
@@ -21,14 +21,14 @@
|
||||
#include "dsp/core/ituround.h"
|
||||
#include "dsp/core/q.h"
|
||||
#include "dsp/core/twixt8.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
@@ -203,8 +203,8 @@ void *Gyarados(long dyw, long dxw, int dst[dyw][dxw], long syw, long sxw,
|
||||
CHECK_LE(sxn, sxw);
|
||||
CHECK_LE(dyn, dyw);
|
||||
CHECK_LE(dxn, dxw);
|
||||
CHECK_LT(bsrl(syn) + bsrl(sxn), 32);
|
||||
CHECK_LT(bsrl(dyn) + bsrl(dxn), 32);
|
||||
CHECK_LT(_bsrl(syn) + _bsrl(sxn), 32);
|
||||
CHECK_LT(_bsrl(dyn) + _bsrl(dxn), 32);
|
||||
CHECK_LE(dyw, 0x7fff);
|
||||
CHECK_LE(dxw, 0x7fff);
|
||||
CHECK_LE(syw, 0x7fff);
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
* @see ttyconfig(), ttyrestore()
|
||||
*/
|
||||
int ttyconfig(int ttyfd, ttyconf_f fn, int64_t arg,
|
||||
const struct termios *opt_out_oldconf) {
|
||||
struct termios *opt_out_oldconf) {
|
||||
struct termios conf[2];
|
||||
if (tcgetattr(ttyfd, &conf[0]) != -1 &&
|
||||
fn(memcpy(&conf[1], &conf[0], sizeof(conf[0])), arg) != -1 &&
|
||||
|
||||
+4
-3
@@ -83,10 +83,11 @@ int ttyident(struct TtyIdent *ti, int ttyinfd, int ttyoutfd) {
|
||||
if (ttyident_probe(ti, ttyinfd, ttyoutfd, "\e[>c") != -1) {
|
||||
rc = 0;
|
||||
memset(&outer, 0, sizeof(outer));
|
||||
if (ti->id == 83 /* GNU Screen */ && (ti->next || weaken(malloc)) &&
|
||||
if (ti->id == 83 /* GNU Screen */ && (ti->next || _weaken(malloc)) &&
|
||||
ttyident_probe(&outer, ttyinfd, ttyoutfd, "\eP\e[>c\e\\") != -1 &&
|
||||
(ti->next = (ti->next ? ti->next
|
||||
: weaken(malloc)(sizeof(struct TtyIdent))))) {
|
||||
(ti->next =
|
||||
(ti->next ? ti->next
|
||||
: _weaken(malloc)(sizeof(struct TtyIdent))))) {
|
||||
memcpy(ti->next, &outer, sizeof(outer));
|
||||
} else {
|
||||
free_s(&ti->next);
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ int ttysendtitle(int, const char *, const struct TtyIdent *);
|
||||
int ttyident(struct TtyIdent *, int, int);
|
||||
void ttyidentclear(struct TtyIdent *);
|
||||
char *ttydescribe(char *, size_t, const struct TtyIdent *);
|
||||
int ttyconfig(int, ttyconf_f, int64_t, const struct termios *);
|
||||
int ttyconfig(int, ttyconf_f, int64_t, struct termios *);
|
||||
int ttyrestore(int, const struct termios *);
|
||||
int ttysetrawdeadline(struct termios *, int64_t);
|
||||
int ttysetrawmode(struct termios *, int64_t);
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xsigaction.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
@@ -59,9 +59,15 @@
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!IsAsan()) {
|
||||
printf("this example is intended for MODE=asan or MODE=dbg\n");
|
||||
kprintf("this example is intended for MODE=asan or MODE=dbg\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
kprintf("SIMULATING CRASH\n");
|
||||
kprintf("----------------\n");
|
||||
|
||||
char *buffer;
|
||||
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||
buffer = malloc(13);
|
||||
|
||||
+7
-7
@@ -20,22 +20,22 @@ int main(int argc, char *argv[]) {
|
||||
volatile unsigned long x;
|
||||
struct timespec now, start, next, interval;
|
||||
printf("hammering the cpu...\n");
|
||||
next = start = _timespec_mono();
|
||||
interval = _timespec_frommillis(500);
|
||||
next = _timespec_add(next, interval);
|
||||
next = start = timespec_mono();
|
||||
interval = timespec_frommillis(500);
|
||||
next = timespec_add(next, interval);
|
||||
for (;;) {
|
||||
for (i = 0;; ++i) {
|
||||
x *= 7;
|
||||
if (!(i % 256)) {
|
||||
now = _timespec_mono();
|
||||
if (_timespec_gte(now, next)) {
|
||||
now = timespec_mono();
|
||||
if (timespec_cmp(now, next) >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
next = _timespec_add(next, interval);
|
||||
next = timespec_add(next, interval);
|
||||
printf("consumed %10g seconds monotonic time and %10g seconds cpu time\n",
|
||||
_timespec_tonanos(_timespec_sub(now, start)) / 1000000000.,
|
||||
timespec_tonanos(timespec_sub(now, start)) / 1000000000.,
|
||||
(double)clock() / CLOCKS_PER_SEC);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
int n;
|
||||
int shown[64];
|
||||
|
||||
void show(int clock) {
|
||||
int i;
|
||||
struct timespec ts;
|
||||
if (clock == 127) return;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (shown[i] == clock) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
shown[n++] = clock;
|
||||
if (clock_getres(clock, &ts) != -1) {
|
||||
kprintf("%s %'ld ns\n", DescribeClockName(clock), timespec_tonanos(ts));
|
||||
} else {
|
||||
kprintf("%s %s\n", DescribeClockName(clock), _strerrno(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
show(CLOCK_REALTIME);
|
||||
show(CLOCK_REALTIME_FAST);
|
||||
show(CLOCK_REALTIME_PRECISE);
|
||||
show(CLOCK_REALTIME_COARSE);
|
||||
show(CLOCK_MONOTONIC);
|
||||
show(CLOCK_MONOTONIC_RAW);
|
||||
show(CLOCK_MONOTONIC_FAST);
|
||||
show(CLOCK_MONOTONIC_PRECISE);
|
||||
show(CLOCK_MONOTONIC_COARSE);
|
||||
show(CLOCK_PROCESS_CPUTIME_ID);
|
||||
show(CLOCK_THREAD_CPUTIME_ID);
|
||||
show(CLOCK_PROF);
|
||||
show(CLOCK_BOOTTIME);
|
||||
show(CLOCK_REALTIME_ALARM);
|
||||
show(CLOCK_BOOTTIME_ALARM);
|
||||
show(CLOCK_TAI);
|
||||
show(CLOCK_UPTIME);
|
||||
show(CLOCK_UPTIME_PRECISE);
|
||||
show(CLOCK_UPTIME_FAST);
|
||||
show(CLOCK_SECOND);
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
+5
-2
@@ -9,18 +9,21 @@
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/appendresourcereport.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
@@ -151,7 +154,7 @@ int main(int argc, char *argv[]) {
|
||||
while ((line = linenoiseWithHistory(prompt, "cmd"))) {
|
||||
n = 0;
|
||||
start = line;
|
||||
if (startswith(start, "time ")) {
|
||||
if (_startswith(start, "time ")) {
|
||||
timeit = true;
|
||||
start += 5;
|
||||
} else {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
||||
@@ -24,6 +25,12 @@
|
||||
*/
|
||||
|
||||
noubsan int main(int argc, char *argv[]) {
|
||||
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
kprintf("SIMULATING CRASH\n");
|
||||
kprintf("----------------\n");
|
||||
|
||||
volatile int64_t x;
|
||||
ShowCrashReports();
|
||||
return 1 / (x = 0);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
||||
+2
-1
@@ -8,7 +8,8 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xiso8601.h"
|
||||
|
||||
/**
|
||||
* @fileoverview ISO-8601 international high-precision timestamp printer.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
|
||||
+26
-1
@@ -49,12 +49,12 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
@@ -71,18 +71,24 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_ZIPOS \
|
||||
NET_HTTP \
|
||||
NET_HTTPS \
|
||||
THIRD_PARTY_AWK \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_DOUBLECONVERSION \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LINENOISE \
|
||||
THIRD_PARTY_LUA \
|
||||
THIRD_PARTY_HIREDIS \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_NSYNC \
|
||||
THIRD_PARTY_NSYNC_MEM \
|
||||
THIRD_PARTY_QUICKJS \
|
||||
THIRD_PARTY_SED \
|
||||
THIRD_PARTY_STB \
|
||||
THIRD_PARTY_TR \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_ZLIB \
|
||||
TOOL_BUILD_LIB \
|
||||
@@ -141,6 +147,25 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
|
||||
$(EXAMPLES_BOOTLOADER)
|
||||
@$(APELINK)
|
||||
|
||||
# # force symtab.com to be a zip file, by pulling a zip asset into linkage
|
||||
# # we wouldn't need to do this if we depended on functions like localtime
|
||||
# o/$(MODE)/examples/symtab.com.dbg: \
|
||||
# $(EXAMPLES_DEPS) \
|
||||
# o/$(MODE)/examples/symtab.o \
|
||||
# o/$(MODE)/examples/symtab.c.zip.o \
|
||||
# o/$(MODE)/examples/examples.pkg \
|
||||
# $(EXAMPLES_BOOTLOADER)
|
||||
# @$(APELINK)
|
||||
|
||||
# modify .com so it can read the symbol table without needing the .com.dbg file
|
||||
o/$(MODE)/examples/symtab.com: \
|
||||
o/$(MODE)/examples/symtab.com.dbg \
|
||||
o/$(MODE)/third_party/zip/zip.com \
|
||||
o/$(MODE)/tool/build/symtab.com
|
||||
@$(MAKE_OBJCOPY)
|
||||
@$(MAKE_SYMTAB_CREATE)
|
||||
@$(MAKE_SYMTAB_ZIP)
|
||||
|
||||
o/$(MODE)/examples/picol.o: private \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
+1
-8
@@ -9,19 +9,12 @@
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/nt/process.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
dontinline void dostuff(const char *s) {
|
||||
int i, us;
|
||||
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
|
||||
srand(_rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
|
||||
for (i = 0; i < 5; ++i) {
|
||||
us = rand() % 500000;
|
||||
usleep(us);
|
||||
|
||||
@@ -7,14 +7,11 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/math.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
STATIC_YOINK("vga_console");
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
volatile long double x = -.5;
|
||||
volatile long double y = 1.5;
|
||||
printf("Hello World! %.19Lg\n", atan2l(x, y));
|
||||
return 0;
|
||||
char *p = _gc(malloc(64));
|
||||
strcpy(p, "this memory is free'd when main() returns");
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
int main() {
|
||||
kprintf("%d\n", GetCpuCount());
|
||||
kprintf("%d\n", _getcpucount());
|
||||
}
|
||||
@@ -7,20 +7,22 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/stdio/xorshift.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/xorshift.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
@@ -101,7 +103,7 @@ uint64_t rngset64(void) {
|
||||
static unsigned i;
|
||||
static uint64_t s;
|
||||
if (!i) {
|
||||
s = rand64();
|
||||
s = _rand64();
|
||||
i = (s + 1) & (511);
|
||||
}
|
||||
return MarsagliaXorshift64(&s);
|
||||
@@ -214,7 +216,7 @@ const struct Function {
|
||||
{"moby", moby}, //
|
||||
{"mt19937", _mt19937}, //
|
||||
{"python", pythonx2}, //
|
||||
{"rand64", rand64}, //
|
||||
{"rand64", _rand64}, //
|
||||
{"rdrand", rdrand}, //
|
||||
{"rdrnd", rdrand}, //
|
||||
{"rdseed", rdseed}, //
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
@@ -136,7 +136,7 @@ void *Worker(void *id) {
|
||||
setsockopt(server, SOL_TCP, TCP_QUICKACK, &yes, sizeof(yes));
|
||||
errno = 0;
|
||||
|
||||
if (bind(server, &addr, sizeof(addr)) == -1) {
|
||||
if (bind(server, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
kprintf("%s() failed %m\n", "socket");
|
||||
goto CloseWorker;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ void *Worker(void *id) {
|
||||
|
||||
// wait for client connection
|
||||
clientaddrsize = sizeof(clientaddr);
|
||||
client = accept(server, &clientaddr, &clientaddrsize);
|
||||
client = accept(server, (struct sockaddr *)&clientaddr, &clientaddrsize);
|
||||
|
||||
// accept() can raise a very diverse number of errors but none of
|
||||
// them are really true showstoppers that would necessitate us to
|
||||
@@ -298,7 +298,7 @@ int main(int argc, char *argv[]) {
|
||||
PORT);
|
||||
}
|
||||
|
||||
threads = argc > 1 ? atoi(argv[1]) : GetCpuCount();
|
||||
threads = argc > 1 ? atoi(argv[1]) : _getcpucount();
|
||||
if (!(1 <= threads && threads <= 100000)) {
|
||||
kprintf("error: invalid number of threads: %d\n", threads);
|
||||
exit(1);
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xsigaction.h"
|
||||
|
||||
const struct itimerval kHertz = {
|
||||
{1, 0},
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#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/runtime/runtime.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/hiredis/hiredis.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Demo of using hiredis to connect to a Redis server
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3 || argc > 5) {
|
||||
fprintf(stderr, "Usage: %s HOST PORT [KEY] [VALUE]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bool setValue = (argc == 5), getValue = (argc == 4);
|
||||
|
||||
redisContext *c = redisConnect(argv[1], atoi(argv[2]));
|
||||
if (c == NULL || c->err) {
|
||||
if (c) {
|
||||
fprintf(stderr, "Connection error: %s\n", c->errstr);
|
||||
redisFree(c);
|
||||
} else {
|
||||
fputs("Failed to allocate redis context\n", stderr);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
redisReply *reply;
|
||||
if (!setValue && !getValue) {
|
||||
reply = redisCommand(c, "PING");
|
||||
printf("PING: %s\n", reply->str);
|
||||
} else if (setValue) {
|
||||
reply = redisCommand(c, "SET %s %s", argv[3], argv[4]);
|
||||
printf("SET: %s\n", reply->str);
|
||||
} else {
|
||||
reply = redisCommand(c, "GET %s", argv[3]);
|
||||
printf("GET: %s\n", reply->str);
|
||||
}
|
||||
|
||||
freeReplyObject(reply);
|
||||
redisFree(c);
|
||||
return 0;
|
||||
}
|
||||
+6
-4
@@ -9,9 +9,11 @@
|
||||
#endif
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/http.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
@@ -43,15 +45,15 @@ void PrintImg(const char *path) {
|
||||
size_t n;
|
||||
int opt, i, yn, xn, cn, w, h;
|
||||
void *img, *pix, *src, *mime;
|
||||
if (!(img = gc(xslurp(path, &n)))) exit(2);
|
||||
if (!(pix = gc(stbi_load_from_memory(img, n, &xn, &yn, &cn, 0)))) exit(3);
|
||||
if (!(img = _gc(xslurp(path, &n)))) exit(2);
|
||||
if (!(pix = _gc(stbi_load_from_memory(img, n, &xn, &yn, &cn, 0)))) exit(3);
|
||||
if (linktag) {
|
||||
printf("<a href=\"%s\"\n >", path);
|
||||
}
|
||||
src = path;
|
||||
if (datauri) {
|
||||
src = xasprintf("data:%s;base64,%s", FindContentType(path, -1),
|
||||
gc(EncodeBase64(img, n, &n)));
|
||||
_gc(EncodeBase64(img, n, &n)));
|
||||
}
|
||||
w = (xn + (1 << scale) / 2) >> scale;
|
||||
h = (yn + (1 << scale) / 2) >> scale;
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/arraylist.internal.h"
|
||||
#include "libc/mem/critbit0.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecode.internal.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
STATIC_YOINK("zip_uri_support");
|
||||
|
||||
/**
|
||||
* @fileoverview Simple Interactive Spell Checker.
|
||||
*
|
||||
* This is an attempt to get spell checking to work in Emacs across
|
||||
* platforms. While the computer science behind spell checking is very
|
||||
* simple, unfortunately Emacs probes all these System Five spell progs
|
||||
* similar to how websites have been known to probe User-Agent strings.
|
||||
*
|
||||
* Here's how we believe the repl works:
|
||||
*
|
||||
* $ make -j8 o//examples/ispell.com
|
||||
* $ o//examples/ispell.com
|
||||
* @(#) Cosmopolitan Ispell Version 3.4.00 8 Feb 2015
|
||||
* word: hello
|
||||
* ok
|
||||
* word: héllo
|
||||
* how about: hills, hello, hilly, jello
|
||||
* word: lova
|
||||
* how about: diva, dona, dora, dove, elva, fora, hove, iota
|
||||
* word: hecruhecrue
|
||||
* not found
|
||||
*
|
||||
* The dictionary for this program is embedded as a text file within the
|
||||
* zip structure of the binary. It can be edited after distribution.
|
||||
*
|
||||
* It's possible to go even fancier than what this code is doing, by
|
||||
* using cmudict phonemes, bloom filters, unicode tables e.g. e vs. é,
|
||||
* and even doing ML similar to Google's online spell checker.
|
||||
*
|
||||
* TODO: Figure out why Emacs rejects this interface.
|
||||
*/
|
||||
|
||||
#define MISSING_LETTER_DISTANCE 5
|
||||
#define MAX_NEARBY_WORD_DISTANCE 6
|
||||
#define MAX_NEARBY_RESULTS 8
|
||||
|
||||
FILE *f;
|
||||
char *line;
|
||||
size_t linesize;
|
||||
const char *query;
|
||||
struct critbit0 words; /* does O(log 𝑛) fast path lookup */
|
||||
|
||||
struct NearbyWords {
|
||||
size_t i, n;
|
||||
struct WordMatch {
|
||||
long dist;
|
||||
char *word;
|
||||
} * p;
|
||||
} nearby;
|
||||
|
||||
long WordDistance(const char *a, const char *b) {
|
||||
long dist;
|
||||
int gota, gotb;
|
||||
unsigned long h, p;
|
||||
wint_t chara, charb;
|
||||
dist = p = 0;
|
||||
for (;;) {
|
||||
gota = abs(tpdecode(a, &chara)); /* parses utf-8 multibyte characters */
|
||||
gotb = abs(tpdecode(b, &charb)); /* abs() handles -1, always yields � */
|
||||
if (!chara && !charb) break;
|
||||
if (!chara || !charb) {
|
||||
dist += MISSING_LETTER_DISTANCE;
|
||||
} else if ((h = hamming(chara, charb))) {
|
||||
dist += h + p++; /* penalize multiple mismatched letters */
|
||||
}
|
||||
if (chara) a += gota;
|
||||
if (charb) b += gotb;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
intptr_t ConsiderWord(const char *word, void *arg) {
|
||||
long dist;
|
||||
if ((dist = WordDistance(word, query)) < MAX_NEARBY_WORD_DISTANCE) {
|
||||
append(&nearby, &((struct WordMatch){dist, word}));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CompareWords(const struct WordMatch *a, const struct WordMatch *b) {
|
||||
return a->dist < b->dist;
|
||||
}
|
||||
|
||||
void FindNearbyWords(void) {
|
||||
nearby.i = 0;
|
||||
critbit0_allprefixed(&words, "", ConsiderWord, NULL);
|
||||
qsort(nearby.p, nearby.i, sizeof(struct WordMatch), (void *)CompareWords);
|
||||
}
|
||||
|
||||
void SpellChecker(void) {
|
||||
int i;
|
||||
printf("@(#) Cosmopolitan Ispell Version 3.4.00 8 Feb 2015\r\n");
|
||||
while (!feof(stdin)) {
|
||||
printf("word: ");
|
||||
fflush(stdout);
|
||||
if (getline(&line, &linesize, stdin) > 0) {
|
||||
query = strtolower(_chomp(line));
|
||||
if (critbit0_contains(&words, query)) {
|
||||
printf("ok\r\n");
|
||||
} else {
|
||||
FindNearbyWords();
|
||||
if (nearby.i) {
|
||||
printf("how about: ");
|
||||
for (i = 0; i < MIN(MAX_NEARBY_RESULTS, nearby.i); ++i) {
|
||||
if (i) printf(", ");
|
||||
fputs(nearby.p[i].word, stdout);
|
||||
}
|
||||
printf("\r\n");
|
||||
} else {
|
||||
printf("not found\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
CHECK_NE(-1, fclose(stdin));
|
||||
CHECK_NE(-1, fclose(stdout));
|
||||
}
|
||||
|
||||
void LoadWords(void) {
|
||||
CHECK_NOTNULL((f = fopen("/zip/usr/share/dict/words", "r")));
|
||||
while (getline(&line, &linesize, f) > 0) {
|
||||
critbit0_insert(&words, strtolower(_chomp(line)));
|
||||
}
|
||||
CHECK_NE(-1, fclose(f));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!NoDebug()) ShowCrashReports();
|
||||
LoadWords();
|
||||
SpellChecker();
|
||||
return 0;
|
||||
}
|
||||
+3
-3
@@ -58,14 +58,14 @@ Contact: [email protected]\"\n\
|
||||
#endif
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
@@ -355,7 +355,7 @@ int getCursorPosition(int64_t ifd, int64_t ofd, int *rows, int *cols) {
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int getWindowSize(int64_t ifd, int64_t ofd, int *rows, int *cols) {
|
||||
struct winsize ws;
|
||||
if (getttysize(STDOUT_FILENO, &ws) == -1 || ws.ws_col == 0) {
|
||||
if (_getttysize(1, &ws) == -1 || ws.ws_col == 0) {
|
||||
/* ioctl() failed. Try to query the terminal itself. */
|
||||
int orig_row, orig_col, retval;
|
||||
|
||||
|
||||
+3
-3
@@ -11,12 +11,12 @@
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
|
||||
struct stat st;
|
||||
|
||||
@@ -49,7 +49,7 @@ void List(const char *path) {
|
||||
const char *vpath;
|
||||
if (strcmp(path, ".") == 0) {
|
||||
vpath = "";
|
||||
} else if (!endswith(path, "/")) {
|
||||
} else if (!_endswith(path, "/")) {
|
||||
vpath = _gc(xasprintf("%s/", path));
|
||||
} else {
|
||||
vpath = path;
|
||||
|
||||
+5
-4
@@ -7,19 +7,20 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xiso8601.h"
|
||||
|
||||
struct stat st;
|
||||
struct Files {
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,43 @@
|
||||
#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/assert.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
/**
|
||||
* @fileoverview shows how accurate clock_nanosleep() is
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
long i, ns;
|
||||
struct timespec x, y, w;
|
||||
timespec_sleep(timespec_fromnanos(0)); // warmup
|
||||
|
||||
printf("\nrelative sleep\n");
|
||||
for (i = 0; i < 28; ++i) {
|
||||
ns = 1l << i;
|
||||
x = timespec_real();
|
||||
timespec_sleep(timespec_fromnanos(ns));
|
||||
y = timespec_real();
|
||||
printf("%,11ld ns sleep took %,ld ns\n", ns,
|
||||
timespec_tonanos(timespec_sub(y, x)));
|
||||
}
|
||||
|
||||
printf("\nabsolute sleep\n");
|
||||
for (i = 0; i < 28; ++i) {
|
||||
ns = 1l << i;
|
||||
x = timespec_real();
|
||||
timespec_sleep_until(timespec_add(x, timespec_fromnanos(ns)));
|
||||
y = timespec_real();
|
||||
printf("%,11ld ns sleep took %,ld ns\n", ns,
|
||||
timespec_tonanos(timespec_sub(y, x)));
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -10,21 +10,21 @@
|
||||
#include "dsp/tty/itoa8.h"
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/inttypes.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
@@ -39,14 +39,15 @@
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "libc/x/xsigaction.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/libcxx/vector"
|
||||
#include "tool/viz/lib/knobs.h"
|
||||
|
||||
STATIC_YOINK("zip_uri_support");
|
||||
STATIC_YOINK("zipos");
|
||||
|
||||
#define USAGE \
|
||||
" [ROM] [FMV]\n\
|
||||
@@ -286,7 +287,7 @@ void GetTermSize(void) {
|
||||
struct winsize wsize_;
|
||||
wsize_.ws_row = 25;
|
||||
wsize_.ws_col = 80;
|
||||
getttysize(STDIN_FILENO, &wsize_);
|
||||
_getttysize(0, &wsize_);
|
||||
FreeSamplingSolution(ssy_);
|
||||
FreeSamplingSolution(ssx_);
|
||||
tyn_ = wsize_.ws_row * 2;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
+3
-2
@@ -17,14 +17,15 @@
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
#include "tool/build/lib/panel.h"
|
||||
|
||||
/**
|
||||
@@ -76,7 +77,7 @@ void GetTtySize(void) {
|
||||
struct winsize wsize;
|
||||
wsize.ws_row = tyn;
|
||||
wsize.ws_col = txn;
|
||||
getttysize(1, &wsize);
|
||||
_getttysize(1, &wsize);
|
||||
tyn = wsize.ws_row;
|
||||
txn = wsize.ws_col;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
#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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/sockaddr.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/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* @fileoverview fast local network port scanner, e.g.
|
||||
*
|
||||
* make -j8 o//examples/portscan.com
|
||||
* o//examples/portscan.com 10.10.10.0/24 22
|
||||
*/
|
||||
|
||||
const char *FormatIp(char buf[16], uint32_t ip) {
|
||||
snprintf(buf, 16, "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define FormatIp(x) FormatIp(alloca(16), x)
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int port;
|
||||
struct Cidr in;
|
||||
uint32_t netmask;
|
||||
const char *status;
|
||||
struct timeval timeout;
|
||||
uint32_t network_address;
|
||||
uint32_t last_host_address;
|
||||
uint32_t first_host_address;
|
||||
|
||||
if (argc != 3) {
|
||||
PrintUsage:
|
||||
fprintf(stderr,
|
||||
"usage: %s IP/CIDR PORT\n"
|
||||
"example: %s 192.168.0.0/24 22\n",
|
||||
argv[0], argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in = ParseCidr(argv[1], -1);
|
||||
if (in.addr == -1) {
|
||||
fprintf(stderr, "error: bad ip/cidr\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
port = atoi(argv[2]);
|
||||
if (!(1 <= port && port <= 65535)) {
|
||||
fprintf(stderr, "error: bad port\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
if (in.cidr > 30) {
|
||||
fprintf(stderr, "error: maximum supported cidr is 30\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
if (in.cidr < 22) {
|
||||
fprintf(stderr, "error: minimum cidr support right now is 22\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
netmask = -1u << (32 - in.cidr);
|
||||
network_address = in.addr & netmask;
|
||||
first_host_address = network_address + 1;
|
||||
last_host_address = (network_address | ~netmask) - 1;
|
||||
|
||||
assert(last_host_address > first_host_address);
|
||||
assert(last_host_address - first_host_address < 1024);
|
||||
|
||||
fprintf(stderr, "scanning %s through %s\n", FormatIp(first_host_address),
|
||||
FormatIp(last_host_address));
|
||||
|
||||
timeout = timeval_frommillis(100);
|
||||
for (int64_t ip = first_host_address; ip <= last_host_address; ++ip) {
|
||||
if (!fork()) {
|
||||
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
if (!connect(3,
|
||||
(struct sockaddr *)&(struct sockaddr_in){
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(ip),
|
||||
.sin_port = htons(port),
|
||||
},
|
||||
sizeof(struct sockaddr_in))) {
|
||||
status = "open";
|
||||
} else if (errno == ECONNREFUSED) {
|
||||
status = "closed";
|
||||
} else if (errno != EINPROGRESS) {
|
||||
status = _strerrno(errno);
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
if (status) {
|
||||
printf("%-15s %s\n", FormatIp(ip), status);
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (wait(0) == -1 && errno == ECHILD) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/reboot.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char line[8] = {0};
|
||||
if (argc > 1 && !strcmp(argv[1], "-y")) {
|
||||
line[0] = 'y';
|
||||
} else {
|
||||
printf("reboot your computer? yes or no [no] ");
|
||||
fflush(stdout);
|
||||
fgets(line, sizeof(line), stdin);
|
||||
}
|
||||
if (line[0] == 'y' || line[0] == 'Y') {
|
||||
if (reboot(RB_AUTOBOOT)) {
|
||||
printf("system is rebooting...\n");
|
||||
exit(0);
|
||||
} else {
|
||||
perror("reboot");
|
||||
exit(1);
|
||||
}
|
||||
} else if (line[0] == 'n' || line[0] == 'N') {
|
||||
exit(0);
|
||||
} else {
|
||||
printf("error: unrecognized response\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
|
||||
@@ -0,0 +1,521 @@
|
||||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright (c) 2010, 2012 David E. O'Brien │
|
||||
│ Copyright (c) 1980, 1992, 1993 │
|
||||
│ The Regents of the University of California. All rights reserved. │
|
||||
│ │
|
||||
│ Redistribution and use in source and binary forms, with or without │
|
||||
│ modification, are permitted provided that the following conditions │
|
||||
│ are met: │
|
||||
│ 1. Redistributions of source code must retain the above copyright │
|
||||
│ notice, this list of conditions and the following disclaimer. │
|
||||
│ 2. Redistributions in binary form must reproduce the above copyright │
|
||||
│ notice, this list of conditions and the following disclaimer in the │
|
||||
│ documentation and/or other materials provided with the distribution. │
|
||||
│ 3. Neither the name of the University nor the names of its contributors │
|
||||
│ may be used to endorse or promote products derived from this software │
|
||||
│ without specific prior written permission. │
|
||||
│ │
|
||||
│ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND │
|
||||
│ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE │
|
||||
│ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE │
|
||||
│ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE │
|
||||
│ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL │
|
||||
│ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS │
|
||||
│ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) │
|
||||
│ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT │
|
||||
│ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY │
|
||||
│ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF │
|
||||
│ SUCH DAMAGE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/bswap.h"
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/select.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* @fileoverview Terminal Screencast Recorder / Player, e.g.
|
||||
*
|
||||
* make o//examples/script.com
|
||||
* o//examples/script.com -r
|
||||
* # type stuff..
|
||||
* # CTRL-D
|
||||
* o//examples/script.com -p typescript
|
||||
*
|
||||
* @note works on Linux, OpenBSD, NetBSD, FreeBSD, MacOS
|
||||
* @see https://asciinema.org/
|
||||
*/
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD Script (BSD-3 License)\\n\
|
||||
Copyright (c) 2010, 2012 David E. O'Brien\\n\
|
||||
Copyright (c) 1980, 1992, 1993\\n\
|
||||
\tThe Regents of the University of California.\\n\
|
||||
\tAll rights reserved.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
#define DEF_BUF 65536
|
||||
|
||||
struct stamp {
|
||||
uint64_t scr_len; /* amount of data */
|
||||
uint64_t scr_sec; /* time it arrived in seconds... */
|
||||
uint32_t scr_usec; /* ...and microseconds */
|
||||
uint32_t scr_direction; /* 'i', 'o', etc (also indicates endianness) */
|
||||
};
|
||||
|
||||
static FILE *fscript;
|
||||
static int master, slave;
|
||||
static int child;
|
||||
static const char *fname;
|
||||
static char *fmfname;
|
||||
static int qflg, ttyflg;
|
||||
static int usesleep, rawout, showexit;
|
||||
|
||||
static struct termios tt;
|
||||
|
||||
static void done(int) wontreturn;
|
||||
static void doshell(char **);
|
||||
static void finish(void);
|
||||
static void record(FILE *, char *, size_t, int);
|
||||
static void consume(FILE *, off_t, char *, int);
|
||||
static void playback(FILE *) wontreturn;
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int cc;
|
||||
struct termios rtt, stt;
|
||||
struct winsize win;
|
||||
struct timeval tv, *tvp;
|
||||
time_t tvec, start;
|
||||
static char obuf[BUFSIZ];
|
||||
static char ibuf[BUFSIZ];
|
||||
fd_set rfd;
|
||||
int aflg, Fflg, kflg, pflg, ch, k, n;
|
||||
int flushtime, readstdin;
|
||||
int fm_fd, fm_log;
|
||||
|
||||
aflg = Fflg = kflg = pflg = 0;
|
||||
usesleep = 1;
|
||||
rawout = 0;
|
||||
flushtime = 30;
|
||||
fm_fd = -1; /* Shut up stupid "may be used uninitialized" GCC
|
||||
warning. (not needed w/clang) */
|
||||
showexit = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "adeFfkpqrt:")) != -1)
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
aflg = 1;
|
||||
break;
|
||||
case 'd':
|
||||
usesleep = 0;
|
||||
break;
|
||||
case 'e': /* Default behavior, accepted for linux compat */
|
||||
break;
|
||||
case 'F':
|
||||
Fflg = 1;
|
||||
break;
|
||||
case 'k':
|
||||
kflg = 1;
|
||||
break;
|
||||
case 'p':
|
||||
pflg = 1;
|
||||
break;
|
||||
case 'q':
|
||||
qflg = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rawout = 1;
|
||||
break;
|
||||
case 't':
|
||||
flushtime = atoi(optarg);
|
||||
if (flushtime < 0)
|
||||
err(1, "invalid flush time %d", flushtime);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 0) {
|
||||
fname = argv[0];
|
||||
argv++;
|
||||
argc--;
|
||||
} else
|
||||
fname = "typescript";
|
||||
|
||||
if ((fscript = fopen(fname, pflg ? "r" : aflg ? "a" : "w")) == NULL)
|
||||
err(1, "%s", fname);
|
||||
|
||||
if (pflg)
|
||||
playback(fscript);
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &tt) == -1 ||
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) {
|
||||
if (errno != ENOTTY) /* For debugger. */
|
||||
err(1, "tcgetattr/ioctl");
|
||||
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
|
||||
err(1, "openpty");
|
||||
} else {
|
||||
if (openpty(&master, &slave, NULL, &tt, &win) == -1)
|
||||
err(1, "openpty");
|
||||
ttyflg = 1;
|
||||
}
|
||||
|
||||
if (rawout)
|
||||
record(fscript, NULL, 0, 's');
|
||||
|
||||
if (!qflg) {
|
||||
tvec = time(NULL);
|
||||
printf("Script started, output file is %s\n", fname);
|
||||
if (!rawout) {
|
||||
fprintf(fscript, "Script started on %s",
|
||||
ctime(&tvec));
|
||||
if (argv[0]) {
|
||||
showexit = 1;
|
||||
fprintf(fscript, "Command: ");
|
||||
for (k = 0 ; argv[k] ; ++k)
|
||||
fprintf(fscript, "%s%s", k ? " " : "",
|
||||
argv[k]);
|
||||
fprintf(fscript, "\n");
|
||||
}
|
||||
}
|
||||
fflush(fscript);
|
||||
}
|
||||
if (ttyflg) {
|
||||
rtt = tt;
|
||||
cfmakeraw(&rtt);
|
||||
rtt.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
|
||||
}
|
||||
|
||||
child = fork();
|
||||
if (child < 0) {
|
||||
warn("fork");
|
||||
done(1);
|
||||
}
|
||||
if (child == 0) {
|
||||
doshell(argv);
|
||||
}
|
||||
close(slave);
|
||||
|
||||
start = tvec = time(0);
|
||||
readstdin = 1;
|
||||
for (;;) {
|
||||
FD_ZERO(&rfd);
|
||||
FD_SET(master, &rfd);
|
||||
if (readstdin)
|
||||
FD_SET(STDIN_FILENO, &rfd);
|
||||
if (!readstdin && ttyflg) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
readstdin = 1;
|
||||
} else if (flushtime > 0) {
|
||||
tv.tv_sec = flushtime - (tvec - start);
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
} else {
|
||||
tvp = NULL;
|
||||
}
|
||||
n = select(master + 1, &rfd, 0, 0, tvp);
|
||||
if (n < 0 && errno != EINTR)
|
||||
break;
|
||||
if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
|
||||
cc = read(STDIN_FILENO, ibuf, BUFSIZ);
|
||||
if (cc < 0)
|
||||
break;
|
||||
if (cc == 0) {
|
||||
if (tcgetattr(master, &stt) == 0 &&
|
||||
(stt.c_lflag & ICANON) != 0) {
|
||||
write(master, &stt.c_cc[VEOF], 1);
|
||||
}
|
||||
readstdin = 0;
|
||||
}
|
||||
if (cc > 0) {
|
||||
if (rawout)
|
||||
record(fscript, ibuf, cc, 'i');
|
||||
write(master, ibuf, cc);
|
||||
if (kflg && tcgetattr(master, &stt) >= 0 &&
|
||||
((stt.c_lflag & ECHO) == 0)) {
|
||||
fwrite(ibuf, 1, cc, fscript);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n > 0 && FD_ISSET(master, &rfd)) {
|
||||
cc = read(master, obuf, sizeof (obuf));
|
||||
if (cc <= 0)
|
||||
break;
|
||||
write(STDOUT_FILENO, obuf, cc);
|
||||
if (rawout)
|
||||
record(fscript, obuf, cc, 'o');
|
||||
else
|
||||
fwrite(obuf, 1, cc, fscript);
|
||||
}
|
||||
tvec = time(0);
|
||||
if (tvec - start >= flushtime) {
|
||||
fflush(fscript);
|
||||
start = tvec;
|
||||
}
|
||||
if (Fflg)
|
||||
fflush(fscript);
|
||||
}
|
||||
finish();
|
||||
done(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: script [-adfkpqr] [-t time] [file [command ...]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
finish(void)
|
||||
{
|
||||
int e, status;
|
||||
|
||||
if (waitpid(child, &status, 0) == child) {
|
||||
if (WIFEXITED(status))
|
||||
e = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
e = WTERMSIG(status);
|
||||
else /* can't happen */
|
||||
e = 1;
|
||||
done(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
doshell(char **av)
|
||||
{
|
||||
const char *shell;
|
||||
|
||||
shell = getenv("SHELL");
|
||||
if (shell == NULL)
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
close(master);
|
||||
fclose(fscript);
|
||||
free(fmfname);
|
||||
login_tty(slave);
|
||||
setenv("SCRIPT", fname, 1);
|
||||
if (av[0]) {
|
||||
execvp(av[0], av);
|
||||
warn("%s", av[0]);
|
||||
} else {
|
||||
execl(shell, shell, "-i", 0);
|
||||
warn("%s", shell);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
done(int eno)
|
||||
{
|
||||
time_t tvec;
|
||||
|
||||
if (ttyflg)
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
|
||||
tvec = time(NULL);
|
||||
if (rawout)
|
||||
record(fscript, NULL, 0, 'e');
|
||||
if (!qflg) {
|
||||
if (!rawout) {
|
||||
if (showexit)
|
||||
fprintf(fscript, "\nCommand exit status:"
|
||||
" %d", eno);
|
||||
fprintf(fscript,"\nScript done on %s",
|
||||
ctime(&tvec));
|
||||
}
|
||||
printf("\nScript done, output file is %s\n", fname);
|
||||
}
|
||||
fclose(fscript);
|
||||
close(master);
|
||||
exit(eno);
|
||||
}
|
||||
|
||||
static void
|
||||
record(FILE *fp, char *buf, size_t cc, int direction)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct stamp stamp;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
stamp.scr_len = cc;
|
||||
stamp.scr_sec = tv.tv_sec;
|
||||
stamp.scr_usec = tv.tv_usec;
|
||||
stamp.scr_direction = direction;
|
||||
iov[0].iov_len = sizeof(stamp);
|
||||
iov[0].iov_base = &stamp;
|
||||
iov[1].iov_len = cc;
|
||||
iov[1].iov_base = buf;
|
||||
if (writev(fileno(fp), &iov[0], 2) == -1)
|
||||
err(1, "writev");
|
||||
}
|
||||
|
||||
static void
|
||||
consume(FILE *fp, off_t len, char *buf, int reg)
|
||||
{
|
||||
size_t l;
|
||||
|
||||
if (reg) {
|
||||
if (fseeko(fp, len, SEEK_CUR) == -1)
|
||||
err(1, NULL);
|
||||
}
|
||||
else {
|
||||
while (len > 0) {
|
||||
l = MIN(DEF_BUF, len);
|
||||
if (fread(buf, sizeof(char), l, fp) != l)
|
||||
err(1, "cannot read buffer");
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define swapstamp(stamp) do { \
|
||||
if (stamp.scr_direction > 0xff) { \
|
||||
stamp.scr_len = bswap_64(stamp.scr_len); \
|
||||
stamp.scr_sec = bswap_64(stamp.scr_sec); \
|
||||
stamp.scr_usec = bswap_32(stamp.scr_usec); \
|
||||
stamp.scr_direction = bswap_32(stamp.scr_direction); \
|
||||
} \
|
||||
} while (0/*CONSTCOND*/)
|
||||
|
||||
static void
|
||||
termset(void)
|
||||
{
|
||||
struct termios traw;
|
||||
|
||||
if (tcgetattr(STDOUT_FILENO, &tt) == -1) {
|
||||
if (errno != ENOTTY) /* For debugger. */
|
||||
err(1, "tcgetattr");
|
||||
return;
|
||||
}
|
||||
ttyflg = 1;
|
||||
traw = tt;
|
||||
cfmakeraw(&traw);
|
||||
traw.c_lflag |= ISIG;
|
||||
tcsetattr(STDOUT_FILENO, TCSANOW, &traw);
|
||||
}
|
||||
|
||||
static void
|
||||
termreset(void)
|
||||
{
|
||||
if (ttyflg) {
|
||||
tcsetattr(STDOUT_FILENO, TCSADRAIN, &tt);
|
||||
ttyflg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
playback(FILE *fp)
|
||||
{
|
||||
struct timespec tsi, tso;
|
||||
struct stamp stamp;
|
||||
struct stat pst;
|
||||
static char buf[DEF_BUF];
|
||||
off_t nread, save_len;
|
||||
size_t l;
|
||||
time_t tclock;
|
||||
int reg;
|
||||
|
||||
if (fstat(fileno(fp), &pst) == -1)
|
||||
err(1, "fstat failed");
|
||||
|
||||
reg = S_ISREG(pst.st_mode);
|
||||
|
||||
for (nread = 0; !reg || nread < pst.st_size; nread += save_len) {
|
||||
if (fread(&stamp, sizeof(stamp), 1, fp) != 1) {
|
||||
if (reg)
|
||||
err(1, "reading playback header");
|
||||
else
|
||||
break;
|
||||
}
|
||||
swapstamp(stamp);
|
||||
save_len = sizeof(stamp);
|
||||
|
||||
if (reg && stamp.scr_len >
|
||||
(uint64_t)(pst.st_size - save_len) - nread)
|
||||
errx(1, "invalid stamp");
|
||||
|
||||
save_len += stamp.scr_len;
|
||||
tclock = stamp.scr_sec;
|
||||
tso.tv_sec = stamp.scr_sec;
|
||||
tso.tv_nsec = stamp.scr_usec * 1000;
|
||||
|
||||
switch (stamp.scr_direction) {
|
||||
case 's':
|
||||
if (!qflg)
|
||||
printf("Script started on %s",
|
||||
ctime(&tclock));
|
||||
tsi = tso;
|
||||
consume(fp, stamp.scr_len, buf, reg);
|
||||
termset();
|
||||
atexit(termreset);
|
||||
break;
|
||||
case 'e':
|
||||
termreset();
|
||||
if (!qflg)
|
||||
printf("\nScript done on %s",
|
||||
ctime(&tclock));
|
||||
consume(fp, stamp.scr_len, buf, reg);
|
||||
break;
|
||||
case 'i':
|
||||
/* throw input away */
|
||||
consume(fp, stamp.scr_len, buf, reg);
|
||||
break;
|
||||
case 'o':
|
||||
tsi.tv_sec = tso.tv_sec - tsi.tv_sec;
|
||||
tsi.tv_nsec = tso.tv_nsec - tsi.tv_nsec;
|
||||
if (tsi.tv_nsec < 0) {
|
||||
tsi.tv_sec -= 1;
|
||||
tsi.tv_nsec += 1000000000;
|
||||
}
|
||||
if (usesleep)
|
||||
nanosleep(&tsi, NULL);
|
||||
tsi = tso;
|
||||
while (stamp.scr_len > 0) {
|
||||
l = MIN(DEF_BUF, stamp.scr_len);
|
||||
if (fread(buf, sizeof(char), l, fp) != l)
|
||||
err(1, "cannot read buffer");
|
||||
|
||||
write(STDOUT_FILENO, buf, l);
|
||||
stamp.scr_len -= l;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errx(1, "invalid direction");
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
SCRIPT(1) Cosmopolitan General Commands Manual SCRIPT(1)
|
||||
|
||||
𝐍𝐀𝐌𝐄
|
||||
𝘀𝗰𝗿𝗶𝗽𝘁 — make typescript of terminal session
|
||||
|
||||
𝐒𝐘𝐍𝐎𝐏𝐒𝐈𝐒
|
||||
𝘀𝗰𝗿𝗶𝗽𝘁 [-𝗮𝗱𝗲𝗳𝗸𝗽𝗾𝗿] [-𝐅 p̲i̲p̲e̲] [-𝘁 t̲i̲m̲e̲] [f̲i̲l̲e̲ [c̲o̲m̲m̲a̲n̲d̲ .̲.̲.̲]]
|
||||
|
||||
𝐃𝐄𝐒𝐂𝐑𝐈𝐏𝐓𝐈𝐎𝐍
|
||||
The 𝘀𝗰𝗿𝗶𝗽𝘁 utility makes a typescript of everything printed on your termi‐
|
||||
nal. It is useful for students who need a hardcopy record of an interac‐
|
||||
tive session as proof of an assignment, as the typescript file can be
|
||||
printed out later with lpr(1).
|
||||
|
||||
If the argument f̲i̲l̲e̲ is given, 𝘀𝗰𝗿𝗶𝗽𝘁 saves all dialogue in f̲i̲l̲e̲. If no
|
||||
file name is given, the typescript is saved in the file t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲.
|
||||
|
||||
If the argument c̲o̲m̲m̲a̲n̲d̲ is given, 𝘀𝗰𝗿𝗶𝗽𝘁 will run the specified command
|
||||
with an optional argument vector instead of an interactive shell.
|
||||
|
||||
The following options are available:
|
||||
|
||||
-𝗮 Append the output to f̲i̲l̲e̲ or t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲, retaining the prior con‐
|
||||
tents.
|
||||
|
||||
-𝗱 When playing back a session with the -𝗽 flag, do not sleep between
|
||||
records when playing back a timestamped session.
|
||||
|
||||
-𝗲 Accepted for compatibility with u̲t̲i̲l̲-̲l̲i̲n̲u̲x̲ 𝘀𝗰𝗿𝗶𝗽𝘁. The child com‐
|
||||
mand exit status is always the exit status of 𝘀𝗰𝗿𝗶𝗽𝘁.
|
||||
|
||||
-𝐅 p̲i̲p̲e̲
|
||||
Immediately flush output after each write. This will allow a user
|
||||
to create a named pipe using mkfifo(1) and another user may watch
|
||||
the live session using a utility like cat(1).
|
||||
|
||||
-𝗸 Log keys sent to the program as well as output.
|
||||
|
||||
-𝗽 Play back a session recorded with the -𝗿 flag in real time.
|
||||
|
||||
-𝗾 Run in quiet mode, omit the start, stop and command status mes‐
|
||||
sages.
|
||||
|
||||
-𝗿 Record a session with input, output, and timestamping.
|
||||
|
||||
-𝘁 t̲i̲m̲e̲
|
||||
Specify the interval at which the script output file will be
|
||||
flushed to disk, in seconds. A value of 0 causes 𝘀𝗰𝗿𝗶𝗽𝘁 to flush
|
||||
after every character I/O event. The default interval is 30 sec‐
|
||||
onds.
|
||||
|
||||
The script ends when the forked shell (or command) exits (a c̲o̲n̲t̲r̲o̲l̲-̲D̲ to
|
||||
exit the Bourne shell (sh(1)), and e̲x̲i̲t̲, l̲o̲g̲o̲u̲t̲ or c̲o̲n̲t̲r̲o̲l̲-̲D̲ (if i̲g̲n̲o̲r̲e̲e̲o̲f̲
|
||||
is not set) for the C-shell, csh(1)).
|
||||
|
||||
Certain interactive commands, such as vi(1), create garbage in the type‐
|
||||
script file. The 𝘀𝗰𝗿𝗶𝗽𝘁 utility works best with commands that do not ma‐
|
||||
nipulate the screen. The results are meant to emulate a hardcopy terminal,
|
||||
not an addressable one.
|
||||
|
||||
𝐄𝐍𝐕𝐈𝐑𝐎𝐍𝐌𝐄𝐍𝐓
|
||||
The following environment variables are utilized by 𝘀𝗰𝗿𝗶𝗽𝘁:
|
||||
|
||||
SCRIPT
|
||||
The SCRIPT environment variable is added to the sub-shell. If
|
||||
SCRIPT already existed in the users environment, its value is over‐
|
||||
written within the sub-shell. The value of SCRIPT is the name of
|
||||
the t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲ file.
|
||||
|
||||
SHELL If the variable SHELL exists, the shell forked by 𝘀𝗰𝗿𝗶𝗽𝘁 will be
|
||||
that shell. If SHELL is not set, the Bourne shell is assumed.
|
||||
(Most shells set this variable automatically).
|
||||
|
||||
𝐒𝐄𝐄 𝐀𝐋𝐒𝐎
|
||||
csh(1) (for the h̲i̲s̲t̲o̲r̲y̲ mechanism)
|
||||
|
||||
𝐇𝐈𝐒𝐓𝐎𝐑𝐘
|
||||
The 𝘀𝗰𝗿𝗶𝗽𝘁 command appeared in 3.0BSD.
|
||||
|
||||
The -𝗱, -𝗽 and -𝗿 options first appeared in NetBSD 2.0 and were ported to
|
||||
FreeBSD 9.2.
|
||||
|
||||
𝐁𝐔𝐆𝐒
|
||||
The 𝘀𝗰𝗿𝗶𝗽𝘁 utility places 𝗲𝘃𝗲𝗿𝘆𝘁𝗵𝗶𝗻𝗴 in the log file, including linefeeds
|
||||
and backspaces. This is not what the naive user expects.
|
||||
|
||||
It is not possible to specify a command without also naming the script file
|
||||
because of argument parsing compatibility issues.
|
||||
|
||||
When running in -𝗸 mode, echo cancelling is far from ideal. The slave ter‐
|
||||
minal mode is checked for ECHO mode to check when to avoid manual echo log‐
|
||||
ging. This does not work when the terminal is in a raw mode where the pro‐
|
||||
gram being run is doing manual echo.
|
||||
|
||||
If 𝘀𝗰𝗿𝗶𝗽𝘁 reads zero bytes from the terminal, it switches to a mode when it
|
||||
only attempts to read once a second until there is data to read. This pre‐
|
||||
vents 𝘀𝗰𝗿𝗶𝗽𝘁 from spinning on zero-byte reads, but might cause a 1-second
|
||||
delay in processing of user input.
|
||||
|
||||
BSD September 1, 2020 BSD
|
||||
@@ -0,0 +1,39 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/reboot.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char line[8] = {0};
|
||||
if (argc > 1 && !strcmp(argv[1], "-y")) {
|
||||
line[0] = 'y';
|
||||
} else {
|
||||
printf("shutdown your computer? yes or no [no] ");
|
||||
fflush(stdout);
|
||||
fgets(line, sizeof(line), stdin);
|
||||
}
|
||||
if (line[0] == 'y' || line[0] == 'Y') {
|
||||
if (reboot(RB_POWER_OFF)) {
|
||||
printf("system is shutting down...\n");
|
||||
exit(0);
|
||||
} else {
|
||||
perror("reboot");
|
||||
exit(1);
|
||||
}
|
||||
} else if (line[0] == 'n' || line[0] == 'N') {
|
||||
exit(0);
|
||||
} else {
|
||||
printf("error: unrecognized response\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -14,11 +14,11 @@
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xiso8601.h"
|
||||
|
||||
/**
|
||||
* @fileoverview File metadata viewer.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#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/intrin/kprintf.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
/**
|
||||
* @fileoverview example of how to embed symbol table in .com file
|
||||
*
|
||||
* # build our binary
|
||||
* make -j16 o//examples/symtab.com
|
||||
*
|
||||
* # move binary somewhere else
|
||||
* # so it can't find the .com.dbg binary
|
||||
* cp o//examples/symtab.com /tmp
|
||||
*
|
||||
* # run program
|
||||
* # notice that it has a symbolic backtrace
|
||||
* /tmp/symtab.com
|
||||
*
|
||||
* @see examples/examples.mk
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
// this links all the debugging and zip functionality
|
||||
ShowCrashReports();
|
||||
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
kprintf("SIMULATING CRASH\n");
|
||||
kprintf("----------------\n");
|
||||
|
||||
volatile int64_t x;
|
||||
return 1 / (x = 0);
|
||||
}
|
||||
+13
-6
@@ -7,13 +7,20 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Command Interpreter Demo
|
||||
* Yes this works on Windows.
|
||||
*/
|
||||
|
||||
STATIC_YOINK("_tr");
|
||||
STATIC_YOINK("_sed");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (IsWindows()) {
|
||||
system("notepad");
|
||||
} else {
|
||||
system("ls | tr a-z A-Z");
|
||||
}
|
||||
system("x=world\n"
|
||||
"echo hello $x |\n"
|
||||
" tr a-z A-Z |\n"
|
||||
" sed 's/\\(.\\)/\\1 /g'");
|
||||
}
|
||||
+2
-1
@@ -12,10 +12,11 @@
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xspawn.h"
|
||||
|
||||
/**
|
||||
* @fileoverview command for showing how long a command takes
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
|
||||
+5
-5
@@ -24,7 +24,7 @@
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/x/xsigaction.h"
|
||||
|
||||
#define CTRL(C) ((C) ^ 0b01000000)
|
||||
#define WRITE(FD, SLIT) write(FD, SLIT, strlen(SLIT))
|
||||
@@ -80,7 +80,7 @@ int rawmode(void) {
|
||||
}
|
||||
|
||||
void getsize(void) {
|
||||
if (getttysize(1, &wsize) != -1) {
|
||||
if (_getttysize(1, &wsize) != -1) {
|
||||
printf("termios says terminal size is %hu×%hu\r\n", wsize.ws_col,
|
||||
wsize.ws_row);
|
||||
} else {
|
||||
@@ -148,12 +148,12 @@ int main(int argc, char *argv[]) {
|
||||
if (iscntrl(code[0]) && !code[1]) {
|
||||
printf("is CTRL-%c a.k.a. ^%c\r\n", CTRL(code[0]), CTRL(code[0]));
|
||||
if (code[0] == CTRL('C') || code[0] == CTRL('D')) break;
|
||||
} else if (startswith(code, "\e[") && endswith(code, "R")) {
|
||||
} else if (_startswith(code, "\e[") && _endswith(code, "R")) {
|
||||
yn = 1, xn = 1;
|
||||
sscanf(code, "\e[%d;%dR", &yn, &xn);
|
||||
printf("inband signalling says terminal size is %d×%d\r\n", xn, yn);
|
||||
} else if (startswith(code, "\e[<") &&
|
||||
(endswith(code, "m") || endswith(code, "M"))) {
|
||||
} else if (_startswith(code, "\e[<") &&
|
||||
(_endswith(code, "m") || _endswith(code, "M"))) {
|
||||
e = 0, y = 1, x = 1;
|
||||
sscanf(code, "\e[<%d;%d;%d%c", &e, &y, &x, &c);
|
||||
printf("mouse %s at %d×%d\r\n", describemouseevent(e | (c == 'm') << 2),
|
||||
|
||||
+439
-359
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,60 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/isystem/unistd.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Bare Metal VGA TTY demo.
|
||||
*
|
||||
* This program can boot as an operating system. Try it out:
|
||||
*
|
||||
* make -j8 o//examples/vga.com
|
||||
* qemu-system-x86_64 -hda o//examples/vga.com -serial stdio
|
||||
*
|
||||
* Please note that, by default, APE binaries only use the serial port
|
||||
* for stdio. To get the VGA console as an added bonus:
|
||||
*
|
||||
* STATIC_YOINK("vga_console");
|
||||
*
|
||||
* Should be added to the top of your main() program source file.
|
||||
*/
|
||||
|
||||
STATIC_YOINK("vga_console");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
volatile long double x = -.5;
|
||||
volatile long double y = 1.5;
|
||||
struct termios tio;
|
||||
char buf[16];
|
||||
ssize_t res;
|
||||
if (tcgetattr(0, &tio) != -1) {
|
||||
tio.c_lflag &= ~(ECHO | ICANON);
|
||||
tcsetattr(0, TCSANOW, &tio);
|
||||
}
|
||||
write(1, "\e[5n", 4);
|
||||
res = read(0, buf, 4);
|
||||
if (res != 4 || memcmp(buf, "\e[0n", 4) != 0) {
|
||||
printf("res = %d?\n", res);
|
||||
return -1;
|
||||
}
|
||||
printf("\e[92;44mHello World!\e[0m %.19Lg\n", atan2l(x, y));
|
||||
|
||||
// read/print loop so machine doesn't reset on metal
|
||||
for (;;) {
|
||||
if ((res = readansi(0, buf, 16)) > 0) {
|
||||
printf("got \e[97m%`'.*s\e[0m\r\n", res, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/isystem/unistd.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Demo of program crash reporting with Bare Metal VGA TTY.
|
||||
*
|
||||
* make -j8 o//examples/vga2.com
|
||||
* qemu-system-x86_64 -hda o//examples/vga2.com -serial stdio
|
||||
*/
|
||||
|
||||
STATIC_YOINK("vga_console");
|
||||
STATIC_YOINK("_idt");
|
||||
STATIC_YOINK("EfiMain");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
volatile int x = 1;
|
||||
volatile int y = 2;
|
||||
printf("argc = %d\n", argc);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
printf("argv[%d] = \"%s\"\n", i, argv[i]);
|
||||
}
|
||||
printf("\e[92;44mHello World!\e[0m %d\n", 1 / (x + y - 3));
|
||||
for (;;);
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/musl/passwd.h"
|
||||
|
||||
/**
|
||||
* @fileoverview program for broadcasting message to all terminals, e.g.
|
||||
*
|
||||
* o//examples/wall.com hello friends
|
||||
*
|
||||
* Will place some bold text into the top left corners of all terminals:
|
||||
*
|
||||
* Broadcast message from jart@host (pts/4) (Tue Oct 11 03:52:24 2022):
|
||||
* hello friends
|
||||
*
|
||||
* It's useful for having one terminal tab notify your other ones when
|
||||
* something like a long running job completes. In the old days back
|
||||
* when unix systems had multiple users, the wall command provided the
|
||||
* ultimate lulz especially if it's a setuid binary with root privs.
|
||||
*/
|
||||
|
||||
#define GETOPTS "v"
|
||||
#define USAGE \
|
||||
"\
|
||||
Usage: wall.com [-v] [TEXTMSG] [<TEXTMSG]\n\
|
||||
-v increase verbosity\n\
|
||||
Examples:\n\
|
||||
wall.com 'hello my friends'\n\
|
||||
echo hello my friends | wall.com\n\
|
||||
"
|
||||
|
||||
int g_verbose;
|
||||
|
||||
static void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, GETOPTS)) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
g_verbose++;
|
||||
break;
|
||||
case '?':
|
||||
write(1, USAGE, sizeof(USAGE) - 1);
|
||||
exit(0);
|
||||
default:
|
||||
write(2, USAGE, sizeof(USAGE) - 1);
|
||||
exit(64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *GetHost(void) {
|
||||
static char host[254];
|
||||
if (gethostname(host, sizeof(host))) {
|
||||
strcpy(host, "localhost");
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
char *GetTime(void) {
|
||||
int64_t t;
|
||||
struct tm tm;
|
||||
struct timespec ts;
|
||||
clock_gettime(0, &ts);
|
||||
localtime_r(&ts.tv_sec, &tm);
|
||||
return _chomp(asctime(&tm));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
GetOpts(argc, argv);
|
||||
|
||||
// create broadcast banner
|
||||
// we use \e[1m so the text is strong & visually distinct
|
||||
// we use \e[K so it doesn't get lost in a forest of text
|
||||
// we map \n → \r\n because teletype might be in raw mode
|
||||
char *msg = 0;
|
||||
const char *s;
|
||||
appends(&msg, "\e7"); // save cursor position
|
||||
appends(&msg, "\e[H"); // goto top left corne
|
||||
appends(&msg, "\e[K"); // clear line forward
|
||||
appends(&msg, "\e[1m"); // bold text
|
||||
appendf(&msg, "Broadcast message from %s@%s", getpwuid(getuid())->pw_name,
|
||||
GetHost());
|
||||
if (isatty(0) && (s = ttyname(0))) appendf(&msg, " (%s)", s);
|
||||
appendf(&msg, " (%s):\r\n", GetTime());
|
||||
appends(&msg, "\e[K");
|
||||
|
||||
// append broadcast message
|
||||
if (optind < argc) {
|
||||
// use cli arguments as message if they exist
|
||||
for (int i = 0; optind + i < argc; ++i) {
|
||||
if (i) appends(&msg, " ");
|
||||
for (s = argv[optind + i]; *s; ++s) {
|
||||
if (*s == '\n') {
|
||||
appends(&msg, "\r\n\e[K");
|
||||
} else {
|
||||
appendw(&msg, *s & 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// otherwise use stdin as message
|
||||
ssize_t i, rc;
|
||||
char buf[512];
|
||||
while ((rc = read(0, buf, sizeof(buf))) > 0) {
|
||||
for (i = 0; i < rc; ++i) {
|
||||
if (buf[i] == '\n') {
|
||||
appends(&msg, "\r\n\e[K"); // clear line forward
|
||||
} else {
|
||||
appendw(&msg, buf[i] & 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
appends(&msg, "\r\n\e[K\e[0m\e8"); // restore
|
||||
|
||||
// try to send message to all pseudoteletypewriters
|
||||
for (int i = 0;; ++i) {
|
||||
int fd;
|
||||
char pts[32];
|
||||
snprintf(pts, sizeof(pts), "/dev/pts/%d", i);
|
||||
if ((fd = open(pts, O_WRONLY | O_NOCTTY)) == -1) {
|
||||
if (errno == ENOENT) break;
|
||||
if (g_verbose) perror(pts);
|
||||
}
|
||||
write(fd, msg, appendz(msg).i);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright (c) 1980, 1993 │
|
||||
│ The Regents of the University of California. All rights reserved. │
|
||||
│ │
|
||||
│ Redistribution and use in source and binary forms, with or without │
|
||||
│ modification, are permitted provided that the following conditions │
|
||||
│ are met: │
|
||||
│ 1. Redistributions of source code must retain the above copyright │
|
||||
│ notice, this list of conditions and the following disclaimer. │
|
||||
│ 2. Redistributions in binary form must reproduce the above copyright │
|
||||
│ notice, this list of conditions and the following disclaimer in the │
|
||||
│ documentation and/or other materials provided with the distribution. │
|
||||
│ 3. Neither the name of the University nor the names of its contributors │
|
||||
│ may be used to endorse or promote products derived from this software │
|
||||
│ without specific prior written permission. │
|
||||
│ │
|
||||
│ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND │
|
||||
│ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE │
|
||||
│ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE │
|
||||
│ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE │
|
||||
│ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL │
|
||||
│ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS │
|
||||
│ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) │
|
||||
│ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT │
|
||||
│ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY │
|
||||
│ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF │
|
||||
│ SUCH DAMAGE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/mem/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
// clang-format off
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
FreeBSD Whois (BSD-3 License)\\n\
|
||||
Copyright (c) 1980, 1993\\n\
|
||||
\tThe Regents of the University of California.\\n\
|
||||
\tAll rights reserved.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
#define ABUSEHOST "whois.abuse.net"
|
||||
#define ANICHOST "whois.arin.net"
|
||||
#define DENICHOST "whois.denic.de"
|
||||
#define DKNICHOST "whois.dk-hostmaster.dk"
|
||||
#define FNICHOST "whois.afrinic.net"
|
||||
#define GNICHOST "whois.nic.gov"
|
||||
#define IANAHOST "whois.iana.org"
|
||||
#define INICHOST "whois.internic.net"
|
||||
#define KNICHOST "whois.krnic.net"
|
||||
#define LNICHOST "whois.lacnic.net"
|
||||
#define MNICHOST "whois.ra.net"
|
||||
#define PDBHOST "whois.peeringdb.com"
|
||||
#define PNICHOST "whois.apnic.net"
|
||||
#define QNICHOST_TAIL ".whois-servers.net"
|
||||
#define RNICHOST "whois.ripe.net"
|
||||
#define VNICHOST "whois.verisign-grs.com"
|
||||
|
||||
#define DEFAULT_PORT "whois"
|
||||
|
||||
#define WHOIS_RECURSE 0x01
|
||||
#define WHOIS_QUICK 0x02
|
||||
#define WHOIS_SPAM_ME 0x04
|
||||
|
||||
#define CHOPSPAM ">>> Last update of WHOIS database:"
|
||||
|
||||
#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-')
|
||||
|
||||
#define SCAN(p, end, check) \
|
||||
while ((p) < (end)) \
|
||||
if (check) ++(p); \
|
||||
else break
|
||||
|
||||
static struct {
|
||||
const char *suffix, *server;
|
||||
} whoiswhere[] = {
|
||||
/* Various handles */
|
||||
{ "-ARIN", ANICHOST },
|
||||
{ "-NICAT", "at" QNICHOST_TAIL },
|
||||
{ "-NORID", "no" QNICHOST_TAIL },
|
||||
{ "-RIPE", RNICHOST },
|
||||
/* Nominet's whois server doesn't return referrals to JANET */
|
||||
{ ".ac.uk", "ac.uk" QNICHOST_TAIL },
|
||||
{ ".gov.uk", "ac.uk" QNICHOST_TAIL },
|
||||
{ "", IANAHOST }, /* default */
|
||||
{ NULL, NULL } /* safety belt */
|
||||
};
|
||||
|
||||
#define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 }
|
||||
static struct {
|
||||
const char *prefix;
|
||||
size_t len;
|
||||
} whois_referral[] = {
|
||||
WHOIS_REFERRAL("whois:"), /* IANA */
|
||||
WHOIS_REFERRAL("Whois Server:"),
|
||||
WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */
|
||||
WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */
|
||||
WHOIS_REFERRAL("ReferralServer: rwhois://"), /* ARIN */
|
||||
WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* We have a list of patterns for RIRs that assert ignorance rather than
|
||||
* providing referrals. If that happens, we guess that ARIN will be more
|
||||
* helpful. But, before following a referral to an RIR, we check if we have
|
||||
* asked that RIR already, and if so we make another guess.
|
||||
*/
|
||||
static const char *actually_arin[] = {
|
||||
"netname: ERX-NETBLOCK\n", /* APNIC */
|
||||
"netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct {
|
||||
int loop;
|
||||
const char *host;
|
||||
} try_rir[] = {
|
||||
{ 0, ANICHOST },
|
||||
{ 0, RNICHOST },
|
||||
{ 0, PNICHOST },
|
||||
{ 0, FNICHOST },
|
||||
{ 0, LNICHOST },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
reset_rir(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; try_rir[i].host != NULL; i++)
|
||||
try_rir[i].loop = 0;
|
||||
}
|
||||
|
||||
static const char *port = DEFAULT_PORT;
|
||||
|
||||
static const char *choose_server(char *);
|
||||
static struct addrinfo *gethostinfo(const char *, const char *, int);
|
||||
static void s_asprintf(char **ret, const char *format, ...);
|
||||
static void usage(void);
|
||||
static void whois(const char *, const char *, const char *, int);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *country, *host;
|
||||
int ch, flags;
|
||||
|
||||
#ifdef SOCKS
|
||||
SOCKSinit(argv[0]);
|
||||
#endif
|
||||
|
||||
country = host = NULL;
|
||||
flags = 0;
|
||||
while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
host = ANICHOST;
|
||||
break;
|
||||
case 'A':
|
||||
host = PNICHOST;
|
||||
break;
|
||||
case 'b':
|
||||
host = ABUSEHOST;
|
||||
break;
|
||||
case 'c':
|
||||
country = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
host = FNICHOST;
|
||||
break;
|
||||
case 'g':
|
||||
host = GNICHOST;
|
||||
break;
|
||||
case 'h':
|
||||
host = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
host = INICHOST;
|
||||
break;
|
||||
case 'I':
|
||||
host = IANAHOST;
|
||||
break;
|
||||
case 'k':
|
||||
host = KNICHOST;
|
||||
break;
|
||||
case 'l':
|
||||
host = LNICHOST;
|
||||
break;
|
||||
case 'm':
|
||||
host = MNICHOST;
|
||||
break;
|
||||
case 'p':
|
||||
port = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
host = PDBHOST;
|
||||
break;
|
||||
case 'Q':
|
||||
flags |= WHOIS_QUICK;
|
||||
break;
|
||||
case 'r':
|
||||
host = RNICHOST;
|
||||
break;
|
||||
case 'R':
|
||||
flags |= WHOIS_RECURSE;
|
||||
break;
|
||||
case 'S':
|
||||
flags |= WHOIS_SPAM_ME;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!argc || (country != NULL && host != NULL))
|
||||
usage();
|
||||
|
||||
/*
|
||||
* If no host or country is specified, rely on referrals from IANA.
|
||||
*/
|
||||
if (host == NULL && country == NULL) {
|
||||
if ((host = getenv("WHOIS_SERVER")) == NULL &&
|
||||
(host = getenv("RA_SERVER")) == NULL) {
|
||||
if (!(flags & WHOIS_QUICK))
|
||||
flags |= WHOIS_RECURSE;
|
||||
}
|
||||
}
|
||||
while (argc-- > 0) {
|
||||
if (country != NULL) {
|
||||
char *qnichost;
|
||||
s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL);
|
||||
whois(*argv, qnichost, port, flags);
|
||||
free(qnichost);
|
||||
} else
|
||||
whois(*argv, host != NULL ? host :
|
||||
choose_server(*argv), port, flags);
|
||||
reset_rir();
|
||||
argv++;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
choose_server(char *domain)
|
||||
{
|
||||
size_t len = strlen(domain);
|
||||
int i;
|
||||
|
||||
for (i = 0; whoiswhere[i].suffix != NULL; i++) {
|
||||
size_t suffix_len = strlen(whoiswhere[i].suffix);
|
||||
if (len > suffix_len &&
|
||||
strcasecmp(domain + len - suffix_len,
|
||||
whoiswhere[i].suffix) == 0)
|
||||
return (whoiswhere[i].server);
|
||||
}
|
||||
errx(EX_SOFTWARE, "no default whois server");
|
||||
}
|
||||
|
||||
static struct addrinfo *
|
||||
gethostinfo(const char *host, const char *hport, int exit_on_noname)
|
||||
{
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
res = NULL;
|
||||
error = getaddrinfo(host, hport, &hints, &res);
|
||||
if (error && (exit_on_noname || error != EAI_NONAME))
|
||||
err(EX_NOHOST, "%s: %s", host, gai_strerror(error));
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for asprintf(3) that exits on error.
|
||||
*/
|
||||
static void
|
||||
s_asprintf(char **ret, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
if (vasprintf(ret, format, ap) == -1) {
|
||||
va_end(ap);
|
||||
err(EX_OSERR, "vasprintf()");
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int
|
||||
connect_to_any_host(struct addrinfo *hostres)
|
||||
{
|
||||
struct addrinfo *res;
|
||||
nfds_t i, j;
|
||||
size_t count;
|
||||
struct pollfd *fds;
|
||||
int timeout = 180, s = -1;
|
||||
|
||||
for (res = hostres, count = 0; res; res = res->ai_next)
|
||||
count++;
|
||||
fds = calloc(count, sizeof(*fds));
|
||||
if (fds == NULL)
|
||||
err(EX_OSERR, "calloc()");
|
||||
|
||||
/*
|
||||
* Traverse the result list elements and make non-block
|
||||
* connection attempts.
|
||||
*/
|
||||
count = i = 0;
|
||||
for (res = hostres; res != NULL; res = res->ai_next) {
|
||||
s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK,
|
||||
res->ai_protocol);
|
||||
if (s < 0)
|
||||
continue;
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
/* Add the socket to poll list */
|
||||
fds[i].fd = s;
|
||||
fds[i].events = POLLERR | POLLHUP |
|
||||
POLLIN | POLLOUT;
|
||||
/*
|
||||
* From here until a socket connects, the
|
||||
* socket fd is owned by the fds[] poll array.
|
||||
*/
|
||||
s = -1;
|
||||
count++;
|
||||
i++;
|
||||
} else {
|
||||
close(s);
|
||||
s = -1;
|
||||
|
||||
/*
|
||||
* Poll only if we have something to poll,
|
||||
* otherwise just go ahead and try next
|
||||
* address
|
||||
*/
|
||||
if (count == 0)
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* If we are at the last address, poll until a connection is
|
||||
* established or we failed all connection attempts.
|
||||
*/
|
||||
if (res->ai_next == NULL)
|
||||
timeout = INFTIM;
|
||||
|
||||
/*
|
||||
* Poll the watched descriptors for successful connections:
|
||||
* if we still have more untried resolved addresses, poll only
|
||||
* once; otherwise, poll until all descriptors have errors,
|
||||
* which will be considered as ETIMEDOUT later.
|
||||
*/
|
||||
do {
|
||||
int n;
|
||||
|
||||
n = poll(fds, i, timeout);
|
||||
if (n == 0) {
|
||||
/*
|
||||
* No event reported in time. Try with a
|
||||
* smaller timeout (but cap at 2-3ms)
|
||||
* after a new host have been added.
|
||||
*/
|
||||
if (timeout >= 3)
|
||||
timeout >>= 1;
|
||||
|
||||
break;
|
||||
} else if (n < 0) {
|
||||
/*
|
||||
* errno here can only be EINTR which we would
|
||||
* want to clean up and bail out.
|
||||
*/
|
||||
s = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for the event(s) we have seen.
|
||||
*/
|
||||
for (j = 0; j < i; j++) {
|
||||
if (fds[j].fd == -1 || fds[j].events == 0 ||
|
||||
fds[j].revents == 0)
|
||||
continue;
|
||||
if (fds[j].revents & ~(POLLIN | POLLOUT)) {
|
||||
close(fds[j].fd);
|
||||
fds[j].fd = -1;
|
||||
fds[j].events = 0;
|
||||
count--;
|
||||
continue;
|
||||
} else if (fds[j].revents & (POLLIN | POLLOUT)) {
|
||||
/* Connect succeeded. */
|
||||
s = fds[j].fd;
|
||||
fds[j].fd = -1;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
} while (timeout == INFTIM && count != 0);
|
||||
}
|
||||
|
||||
/* All attempts were failed */
|
||||
s = -1;
|
||||
if (count == 0)
|
||||
errno = ETIMEDOUT;
|
||||
|
||||
done:
|
||||
/* Close all watched fds except the succeeded one */
|
||||
for (j = 0; j < i; j++)
|
||||
if (fds[j].fd != -1)
|
||||
close(fds[j].fd);
|
||||
free(fds);
|
||||
return (s);
|
||||
}
|
||||
|
||||
static void
|
||||
whois(const char *query, const char *hostname, const char *hostport, int flags)
|
||||
{
|
||||
FILE *fp;
|
||||
struct addrinfo *hostres;
|
||||
char *buf, *host, *nhost, *nport, *p;
|
||||
int comment, s, f;
|
||||
size_t len, i;
|
||||
|
||||
hostres = gethostinfo(hostname, hostport, 1);
|
||||
s = connect_to_any_host(hostres);
|
||||
if (s == -1)
|
||||
err(EX_OSERR, "connect()");
|
||||
|
||||
/* Restore default blocking behavior. */
|
||||
if ((f = fcntl(s, F_GETFL)) == -1)
|
||||
err(EX_OSERR, "fcntl()");
|
||||
f &= ~O_NONBLOCK;
|
||||
if (fcntl(s, F_SETFL, f) == -1)
|
||||
err(EX_OSERR, "fcntl()");
|
||||
|
||||
fp = fdopen(s, "r+");
|
||||
if (fp == NULL)
|
||||
err(EX_OSERR, "fdopen()");
|
||||
|
||||
if (!(flags & WHOIS_SPAM_ME) &&
|
||||
(strcasecmp(hostname, DENICHOST) == 0 ||
|
||||
strcasecmp(hostname, "de" QNICHOST_TAIL) == 0)) {
|
||||
const char *q;
|
||||
int idn = 0;
|
||||
for (q = query; *q != '\0'; q++)
|
||||
if (!isascii(*q))
|
||||
idn = 1;
|
||||
fprintf(fp, "-T dn%s %s\r\n", idn ? "" : ",ace", query);
|
||||
} else if (!(flags & WHOIS_SPAM_ME) &&
|
||||
(strcasecmp(hostname, DKNICHOST) == 0 ||
|
||||
strcasecmp(hostname, "dk" QNICHOST_TAIL) == 0))
|
||||
fprintf(fp, "--show-handles %s\r\n", query);
|
||||
else if ((flags & WHOIS_SPAM_ME) ||
|
||||
strchr(query, ' ') != NULL)
|
||||
fprintf(fp, "%s\r\n", query);
|
||||
else if (strcasecmp(hostname, ANICHOST) == 0) {
|
||||
if (strncasecmp(query, "AS", 2) == 0 &&
|
||||
strspn(query+2, "0123456789") == strlen(query+2))
|
||||
fprintf(fp, "+ a %s\r\n", query+2);
|
||||
else
|
||||
fprintf(fp, "+ %s\r\n", query);
|
||||
} else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0)
|
||||
fprintf(fp, "domain %s\r\n", query);
|
||||
else
|
||||
fprintf(fp, "%s\r\n", query);
|
||||
fflush(fp);
|
||||
|
||||
comment = 0;
|
||||
if (!(flags & WHOIS_SPAM_ME) &&
|
||||
(strcasecmp(hostname, ANICHOST) == 0 ||
|
||||
strcasecmp(hostname, RNICHOST) == 0)) {
|
||||
comment = 2;
|
||||
}
|
||||
|
||||
nhost = NULL;
|
||||
while ((buf = fgetln(fp, &len)) != NULL) {
|
||||
/* Nominet */
|
||||
if (!(flags & WHOIS_SPAM_ME) &&
|
||||
len == 5 && strncmp(buf, "-- \r\n", 5) == 0)
|
||||
break;
|
||||
/* RIRs */
|
||||
if (comment == 1 && buf[0] == '#')
|
||||
break;
|
||||
else if (comment == 2) {
|
||||
if (strchr("#%\r\n", buf[0]) != NULL)
|
||||
continue;
|
||||
else
|
||||
comment = 1;
|
||||
}
|
||||
|
||||
printf("%.*s", (int)len, buf);
|
||||
|
||||
if ((flags & WHOIS_RECURSE) && nhost == NULL) {
|
||||
for (i = 0; whois_referral[i].prefix != NULL; i++) {
|
||||
p = buf;
|
||||
SCAN(p, buf+len, *p == ' ');
|
||||
if (strncasecmp(p, whois_referral[i].prefix,
|
||||
whois_referral[i].len) != 0)
|
||||
continue;
|
||||
p += whois_referral[i].len;
|
||||
SCAN(p, buf+len, *p == ' ');
|
||||
host = p;
|
||||
SCAN(p, buf+len, ishost(*p));
|
||||
if (p > host) {
|
||||
char *pstr;
|
||||
|
||||
s_asprintf(&nhost, "%.*s",
|
||||
(int)(p - host), host);
|
||||
|
||||
if (*p != ':') {
|
||||
s_asprintf(&nport, "%s", port);
|
||||
break;
|
||||
}
|
||||
|
||||
pstr = ++p;
|
||||
SCAN(p, buf+len, isdigit(*p));
|
||||
if (p > pstr && (p - pstr) < 6) {
|
||||
s_asprintf(&nport, "%.*s",
|
||||
(int)(p - pstr), pstr);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Invalid port; don't recurse */
|
||||
free(nhost);
|
||||
nhost = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (i = 0; actually_arin[i] != NULL; i++) {
|
||||
if (strncmp(buf, actually_arin[i], len) == 0) {
|
||||
s_asprintf(&nhost, "%s", ANICHOST);
|
||||
s_asprintf(&nport, "%s", port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Verisign etc. */
|
||||
if (!(flags & WHOIS_SPAM_ME) &&
|
||||
len >= sizeof(CHOPSPAM)-1 &&
|
||||
(strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 ||
|
||||
strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
freeaddrinfo(hostres);
|
||||
|
||||
f = 0;
|
||||
for (i = 0; try_rir[i].host != NULL; i++) {
|
||||
/* Remember visits to RIRs */
|
||||
if (try_rir[i].loop == 0 &&
|
||||
strcasecmp(try_rir[i].host, hostname) == 0)
|
||||
try_rir[i].loop = 1;
|
||||
/* Do we need to find an alternative RIR? */
|
||||
if (try_rir[i].loop != 0 && nhost != NULL &&
|
||||
strcasecmp(try_rir[i].host, nhost) == 0) {
|
||||
free(nhost);
|
||||
nhost = NULL;
|
||||
free(nport);
|
||||
nport = NULL;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
if (f) {
|
||||
/* Find a replacement RIR */
|
||||
for (i = 0; try_rir[i].host != NULL; i++) {
|
||||
if (try_rir[i].loop == 0) {
|
||||
s_asprintf(&nhost, "%s", try_rir[i].host);
|
||||
s_asprintf(&nport, "%s", port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nhost != NULL) {
|
||||
/* Ignore self-referrals */
|
||||
if (strcasecmp(hostname, nhost) != 0) {
|
||||
printf("# %s\n\n", nhost);
|
||||
whois(query, nhost, nport, flags);
|
||||
}
|
||||
free(nhost);
|
||||
free(nport);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: whois [-aAbfgiIklmPQrRS] [-c country-code | -h hostname] "
|
||||
"[-p port] name ...\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_AR_H_
|
||||
#define COSMOPOLITAN_LIBC_AR_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr {
|
||||
char ar_name[16];
|
||||
char ar_date[12];
|
||||
char ar_uid[6], ar_gid[6];
|
||||
char ar_mode[8];
|
||||
char ar_size[10];
|
||||
char ar_fmag[2];
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_AR_H_ */
|
||||
+58
-4
@@ -4,19 +4,73 @@
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern bool __assert_disable;
|
||||
void __assert_fail(const char *, const char *, int) hidden relegated;
|
||||
void __assert_fail(const char *, const char *, int) _Hide relegated;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(EXPR) ((void)0)
|
||||
#define assert(x) ((void)0)
|
||||
#else
|
||||
#define assert(EXPR) \
|
||||
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
|
||||
#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__), 0)))
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if !defined(TINY) && !defined(MODE_DBG)
|
||||
/**
|
||||
* Specifies expression can't possibly be false.
|
||||
*
|
||||
* This macro uses the `notpossible` keyword and is intended for things
|
||||
* like systems integration, where we know for a fact that something is
|
||||
* never going to happen, but there's no proof. So we don't want to add
|
||||
* extra bloat for filenames and line numbers, since `ShowCrashReports`
|
||||
* can print a backtrace if we just embed the UD2 instruction to crash.
|
||||
* That's useful for systems code, for the following reason. Invariants
|
||||
* make sense with _unassert() since they usually get placed at the top
|
||||
* of functions. But if you used _unassert() to test a system call does
|
||||
* not fail, then check happens at the end of your function usually and
|
||||
* is therefore likely to result in a failure condition where execution
|
||||
* falls through into a different function, which is shocking to debug.
|
||||
*
|
||||
* In `MODE=tiny` these assertions are redefined as undefined behavior.
|
||||
*/
|
||||
#define _npassert(x) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
notpossible; \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
#else
|
||||
#define _npassert(x) _unassert(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/**
|
||||
* Specifies expression being false is undefined behavior.
|
||||
*
|
||||
* This is a good way to tell the compiler about your invariants, which
|
||||
* leads to smaller faster programs. The expression is never removed by
|
||||
* the preprocessor so it's recommended that it be free of side-effects
|
||||
* if you intend for it to be removed. At the same time, this guarantee
|
||||
* makes this assertion useful for things like system calls, since they
|
||||
* won't be removed by `NDEBUG` mode.
|
||||
*
|
||||
* If this assertion fails, the worst possible things can happen unless
|
||||
* you've built your binary in `MODE=dbg` since UBSAN is the only thing
|
||||
* that's capable of debugging this macro.
|
||||
*/
|
||||
#define _unassert(x) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
unreachable; \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */
|
||||
+24
-40
@@ -1,22 +1,8 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_ATOMIC_H_
|
||||
#define COSMOPOLITAN_LIBC_ATOMIC_H_
|
||||
#include "libc/inttypes.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview C11 Atomic Types
|
||||
*
|
||||
* We supoprt C++ and old C compilers. It's recommended you use macros
|
||||
* like `_Atomic(int)` rather than `_Atomic int` or `atomic_int` since
|
||||
* we only define a portability macro for the syntax `_Atomic(T)`.
|
||||
*
|
||||
* @see libc/integral/c.inc
|
||||
* @see libc/intrin/atomic.h
|
||||
*/
|
||||
|
||||
#define atomic_bool _Atomic(_Bool)
|
||||
#define atomic_bool32 atomic_int32
|
||||
#define atomic_bool32 _Atomic(__INT32_TYPE__)
|
||||
#define atomic_char _Atomic(char)
|
||||
#define atomic_schar _Atomic(signed char)
|
||||
#define atomic_uchar _Atomic(unsigned char)
|
||||
@@ -28,29 +14,29 @@ COSMOPOLITAN_C_START_
|
||||
#define atomic_ulong _Atomic(unsigned long)
|
||||
#define atomic_llong _Atomic(long long)
|
||||
#define atomic_ullong _Atomic(unsigned long long)
|
||||
#define atomic_char16_t _Atomic(char16_t)
|
||||
#define atomic_char32_t _Atomic(char32_t)
|
||||
#define atomic_wchar_t _Atomic(wchar_t)
|
||||
#define atomic_intptr_t _Atomic(intptr_t)
|
||||
#define atomic_uintptr_t _Atomic(uintptr_t)
|
||||
#define atomic_size_t _Atomic(size_t)
|
||||
#define atomic_ptrdiff_t _Atomic(ptrdiff_t)
|
||||
#define atomic_int_fast8_t _Atomic(int_fast8_t)
|
||||
#define atomic_uint_fast8_t _Atomic(uint_fast8_t)
|
||||
#define atomic_int_fast16_t _Atomic(int_fast16_t)
|
||||
#define atomic_uint_fast16_t _Atomic(uint_fast16_t)
|
||||
#define atomic_int_fast32_t _Atomic(int_fast32_t)
|
||||
#define atomic_uint_fast32_t _Atomic(uint_fast32_t)
|
||||
#define atomic_int_fast64_t _Atomic(int_fast64_t)
|
||||
#define atomic_uint_fast64_t _Atomic(uint_fast64_t)
|
||||
#define atomic_int_least8_t _Atomic(int_least8_t)
|
||||
#define atomic_uint_least8_t _Atomic(uint_least8_t)
|
||||
#define atomic_int_least16_t _Atomic(int_least16_t)
|
||||
#define atomic_uint_least16_t _Atomic(uint_least16_t)
|
||||
#define atomic_int_least32_t _Atomic(int_least32_t)
|
||||
#define atomic_uint_least32_t _Atomic(uint_least32_t)
|
||||
#define atomic_int_least64_t _Atomic(int_least64_t)
|
||||
#define atomic_uint_least64_t _Atomic(uint_least64_t)
|
||||
#define atomic_char16_t _Atomic(__CHAR16_TYPE__)
|
||||
#define atomic_char32_t _Atomic(__CHAR32_TYPE__)
|
||||
#define atomic_wchar_t _Atomic(__WCHAR_TYPE__)
|
||||
#define atomic_intptr_t _Atomic(__INTPTR_TYPE__)
|
||||
#define atomic_uintptr_t _Atomic(__UINTPTR_TYPE__)
|
||||
#define atomic_size_t _Atomic(__SIZE_TYPE__)
|
||||
#define atomic_ptrdiff_t _Atomic(__PTRDIFF_TYPE__)
|
||||
#define atomic_int_fast8_t _Atomic(__INT_FAST8_TYPE__)
|
||||
#define atomic_uint_fast8_t _Atomic(__UINT_FAST8_TYPE__)
|
||||
#define atomic_int_fast16_t _Atomic(__INT_FAST16_TYPE__)
|
||||
#define atomic_uint_fast16_t _Atomic(__UINT_FAST16_TYPE__)
|
||||
#define atomic_int_fast32_t _Atomic(__INT_FAST32_TYPE__)
|
||||
#define atomic_uint_fast32_t _Atomic(__UINT_FAST32_TYPE__)
|
||||
#define atomic_int_fast64_t _Atomic(__INT_FAST64_TYPE__)
|
||||
#define atomic_uint_fast64_t _Atomic(__UINT_FAST64_TYPE__)
|
||||
#define atomic_int_least8_t _Atomic(__INT_LEAST8_TYPE__)
|
||||
#define atomic_uint_least8_t _Atomic(__UINT_LEAST8_TYPE__)
|
||||
#define atomic_int_least16_t _Atomic(__INT_LEAST16_TYPE__)
|
||||
#define atomic_uint_least16_t _Atomic(__UINT_LEAST16_TYPE__)
|
||||
#define atomic_int_least32_t _Atomic(__INT_LEAST32_TYPE__)
|
||||
#define atomic_uint_least32_t _Atomic(__UINT_LEAST32_TYPE__)
|
||||
#define atomic_int_least64_t _Atomic(__INT_LEAST64_TYPE__)
|
||||
#define atomic_uint_least64_t _Atomic(__UINT_LEAST64_TYPE__)
|
||||
|
||||
#ifdef __CLANG_ATOMIC_BOOL_LOCK_FREE
|
||||
#define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE
|
||||
@@ -76,6 +62,4 @@ COSMOPOLITAN_C_START_
|
||||
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_ATOMIC_H_ */
|
||||
@@ -16,5 +16,6 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sig.internal.h"
|
||||
|
||||
bool __time_critical;
|
||||
struct Signals __sig;
|
||||
@@ -16,26 +16,23 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* @fileoverview UNIX signals for the New Technology, Part 2.
|
||||
* @threadsafe
|
||||
*/
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* Allocates piece of memory for storing pending signal.
|
||||
@@ -61,6 +58,18 @@ static textwindows void __sig_free(struct Signal *mem) {
|
||||
mem->used = false;
|
||||
}
|
||||
|
||||
static inline textwindows int __sig_is_masked(int sig) {
|
||||
if (__tls_enabled) {
|
||||
return __get_tls()->tib_sigmask & (1ull << (sig - 1));
|
||||
} else {
|
||||
return __sig.sigmask & (1ull << (sig - 1));
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int __sig_is_applicable(struct Signal *s) {
|
||||
return s->tid <= 0 || s->tid == gettid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues signal that isn't masked.
|
||||
* @return signal or null if empty or none unmasked
|
||||
@@ -70,7 +79,7 @@ static textwindows struct Signal *__sig_remove(void) {
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (prev = 0, res = __sig.queue; res; prev = res, res = res->next) {
|
||||
if (!sigismember(&__sig.mask, res->sig)) {
|
||||
if (__sig_is_applicable(res) && !__sig_is_masked(res->sig)) {
|
||||
if (res == __sig.queue) {
|
||||
__sig.queue = res->next;
|
||||
} else if (prev) {
|
||||
@@ -78,8 +87,6 @@ static textwindows struct Signal *__sig_remove(void) {
|
||||
}
|
||||
res->next = 0;
|
||||
break;
|
||||
} else {
|
||||
STRACE("%G is masked", res->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
@@ -101,7 +108,6 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
||||
STRACE("delivering %G", sig);
|
||||
|
||||
// enter the signal
|
||||
__sig_lock();
|
||||
rva = __sighandrvas[sig];
|
||||
flags = __sighandflags[sig];
|
||||
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
|
||||
@@ -112,12 +118,11 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
||||
// signal handler. in that case you must use SA_NODEFER.
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
}
|
||||
__sig_unlock();
|
||||
|
||||
// setup the somewhat expensive information args
|
||||
// only if they're requested by the user in sigaction()
|
||||
if (flags & SA_SIGINFO) {
|
||||
__repstosb(&info, 0, sizeof(info));
|
||||
bzero(&info, sizeof(info));
|
||||
info.si_signo = sig;
|
||||
info.si_code = si_code;
|
||||
infop = &info;
|
||||
@@ -134,7 +139,9 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
||||
// since sigaction() is @asyncsignalsafe we only restore it if the
|
||||
// user didn't change it during the signal handler. we also don't
|
||||
// need to do anything if this was a oneshot signal or nodefer.
|
||||
_lockcmpxchg(__sighandrvas + sig, (int32_t)(intptr_t)SIG_DFL, rva);
|
||||
if (__sighandrvas[sig] == (int32_t)(intptr_t)SIG_DFL) {
|
||||
__sighandrvas[sig] = rva;
|
||||
}
|
||||
}
|
||||
|
||||
if (!restartable) {
|
||||
@@ -150,7 +157,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
||||
/**
|
||||
* Returns true if signal default action is to end process.
|
||||
*/
|
||||
static textwindows bool __sig_isfatal(int sig) {
|
||||
static textwindows bool __sig_is_fatal(int sig) {
|
||||
if (sig == SIGCHLD || sig == SIGURG || sig == SIGWINCH) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -168,10 +175,9 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
||||
bool delivered;
|
||||
switch (__sighandrvas[sig]) {
|
||||
case (intptr_t)SIG_DFL:
|
||||
if (__sig_isfatal(sig)) {
|
||||
if (__sig_is_fatal(sig)) {
|
||||
STRACE("terminating on %G", sig);
|
||||
__restorewintty();
|
||||
_Exit(128 + sig);
|
||||
_Exitr(128 + sig);
|
||||
}
|
||||
// fallthrough
|
||||
case (intptr_t)SIG_IGN:
|
||||
@@ -195,20 +201,18 @@ bool __sig_handle(bool restartable, int sig, int si_code, ucontext_t *ctx) {
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_raise(int sig, int si_code) {
|
||||
int rc;
|
||||
int candeliver;
|
||||
__sig_lock();
|
||||
candeliver = !sigismember(&__sig.mask, sig);
|
||||
__sig_unlock();
|
||||
switch (candeliver) {
|
||||
case 1:
|
||||
if (1 <= sig && sig <= 64) {
|
||||
if (!__sig_is_masked(sig)) {
|
||||
++__sig_count;
|
||||
// TODO(jart): ucontext_t support
|
||||
__sig_handle(false, sig, si_code, 0);
|
||||
return 0;
|
||||
case 0:
|
||||
} else {
|
||||
STRACE("%G is masked", sig);
|
||||
return __sig_add(sig, si_code);
|
||||
default:
|
||||
return -1; // sigismember() validates `sig`
|
||||
return __sig_add(gettid(), sig, si_code);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,18 +221,19 @@ textwindows int __sig_raise(int sig, int si_code) {
|
||||
* @return 0 on success, otherwise -1 w/ errno
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows int __sig_add(int sig, int si_code) {
|
||||
textwindows int __sig_add(int tid, int sig, int si_code) {
|
||||
int rc;
|
||||
struct Signal *mem;
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
__sig_lock();
|
||||
if (1 <= sig && sig <= 64) {
|
||||
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
|
||||
STRACE("ignoring %G", sig);
|
||||
rc = 0;
|
||||
} else {
|
||||
STRACE("enqueuing %G", sig);
|
||||
__sig_lock();
|
||||
++__sig_count;
|
||||
if ((mem = __sig_alloc())) {
|
||||
mem->tid = tid;
|
||||
mem->sig = sig;
|
||||
mem->si_code = si_code;
|
||||
mem->next = __sig.queue;
|
||||
@@ -237,8 +242,8 @@ textwindows int __sig_add(int sig, int si_code) {
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
__sig_unlock();
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
@@ -277,7 +282,7 @@ textwindows bool __sig_check(bool restartable) {
|
||||
textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||
struct Signal *cur, *prev, *next;
|
||||
if (rva != (unsigned)(intptr_t)SIG_IGN &&
|
||||
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_isfatal(sig))) {
|
||||
(rva != (unsigned)(intptr_t)SIG_DFL || __sig_is_fatal(sig))) {
|
||||
return;
|
||||
}
|
||||
if (__sig.queue) {
|
||||
@@ -299,25 +304,3 @@ textwindows void __sig_check_ignore(const int sig, const unsigned rva) {
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the pending signals on New Technology.
|
||||
*
|
||||
* @param pending is to hold the pending signals
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_pending(sigset_t *pending) {
|
||||
struct Signal *cur;
|
||||
sigemptyset(pending);
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (cur = __sig.queue; cur; cur = cur->next) {
|
||||
if (__sighandrvas[cur->sig] != (unsigned)(intptr_t)SIG_IGN) {
|
||||
pending->__bits[(cur->sig - 1) >> 6] |= (1ull << ((cur->sig - 1) & 63));
|
||||
} else {
|
||||
STRACE("%G is ignored", cur->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
@@ -16,50 +16,45 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* @fileoverview UNIX signals for the New Technology, Part 1.
|
||||
* @threadsafe
|
||||
*/
|
||||
#define GetSigBit(x) (1ull << (((x)-1) & 63))
|
||||
|
||||
struct Signals __sig; // TODO(jart): Need TLS
|
||||
|
||||
#define GetSigBit(XXSIG) (1ull << (((XXSIG)-1) & 63))
|
||||
|
||||
/**
|
||||
* Changes signal mask for main thread.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
|
||||
int i;
|
||||
uint64_t a, b;
|
||||
uint64_t x, y, *mask;
|
||||
if (how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK) {
|
||||
__sig_lock();
|
||||
if (__tls_enabled) {
|
||||
mask = &__get_tls()->tib_sigmask;
|
||||
} else {
|
||||
mask = &__sig.sigmask;
|
||||
}
|
||||
if (old) {
|
||||
*old = __sig.mask;
|
||||
old->__bits[0] = *mask;
|
||||
old->__bits[1] = 0;
|
||||
}
|
||||
if (neu) {
|
||||
for (i = 0; i < ARRAYLEN(__sig.mask.__bits); ++i) {
|
||||
if (how == SIG_BLOCK) {
|
||||
__sig.mask.__bits[i] |= neu->__bits[i];
|
||||
} else if (how == SIG_UNBLOCK) {
|
||||
__sig.mask.__bits[i] &= ~neu->__bits[i];
|
||||
} else {
|
||||
__sig.mask.__bits[i] = neu->__bits[i];
|
||||
}
|
||||
x = *mask;
|
||||
y = neu->__bits[0];
|
||||
if (how == SIG_BLOCK) {
|
||||
x |= y;
|
||||
} else if (how == SIG_UNBLOCK) {
|
||||
x &= ~y;
|
||||
} else {
|
||||
x = y;
|
||||
}
|
||||
__sig.mask.__bits[0] &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP));
|
||||
x &= ~(0
|
||||
#define M(x) | GetSigBit(x)
|
||||
#include "libc/intrin/sigisprecious.inc"
|
||||
);
|
||||
*mask = x;
|
||||
}
|
||||
__sig_unlock();
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
#undef GetSigBit
|
||||
@@ -0,0 +1,43 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
|
||||
/**
|
||||
* Determines the pending signals on New Technology.
|
||||
*
|
||||
* @param pending is to hold the pending signals
|
||||
* @threadsafe
|
||||
*/
|
||||
textwindows void __sig_pending(sigset_t *pending) {
|
||||
struct Signal *s;
|
||||
sigemptyset(pending);
|
||||
if (__sig.queue) {
|
||||
__sig_lock();
|
||||
for (s = __sig.queue; s; s = s->next) {
|
||||
if (__sig_is_applicable(s) &&
|
||||
__sighandrvas[s->sig] != (unsigned)(intptr_t)SIG_IGN) {
|
||||
sigaddset(pending, s->sig);
|
||||
}
|
||||
}
|
||||
__sig_unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
extern const unsigned FIODGNAME;
|
||||
extern const unsigned TIOCPTSNAME;
|
||||
extern const unsigned TIOCPTYGNAME;
|
||||
|
||||
struct fiodgname_arg {
|
||||
int len;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
struct ptmget {
|
||||
int cfd;
|
||||
int sfd;
|
||||
char cn[1024];
|
||||
char sn[1024];
|
||||
};
|
||||
|
||||
int _ptsname(int fd, char *buf, size_t size) {
|
||||
int pty;
|
||||
size_t n;
|
||||
struct ptmget t;
|
||||
|
||||
if (_isptmaster(fd)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
t.sn[0] = '/';
|
||||
t.sn[1] = 'd';
|
||||
t.sn[2] = 'e';
|
||||
t.sn[3] = 'v';
|
||||
t.sn[4] = '/';
|
||||
t.sn[5] = 0;
|
||||
|
||||
if (IsLinux()) {
|
||||
if (sys_ioctl(fd, TIOCGPTN, &pty)) return -1;
|
||||
t.sn[5] = 'p';
|
||||
t.sn[6] = 't';
|
||||
t.sn[7] = 's';
|
||||
t.sn[8] = '/';
|
||||
FormatInt32(t.sn + 9, pty);
|
||||
} else if (IsXnu()) {
|
||||
if (sys_ioctl(fd, TIOCPTYGNAME, t.sn)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (IsFreebsd()) {
|
||||
struct fiodgname_arg fgn = {sizeof(t.sn) - 5, t.sn + 5};
|
||||
if (sys_ioctl(fd, FIODGNAME, &fgn) == -1) {
|
||||
if (errno == EINVAL) {
|
||||
errno = ERANGE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (IsNetbsd()) {
|
||||
if (sys_ioctl(fd, TIOCPTSNAME, &t)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
if ((n = strlen(t.sn)) < size) {
|
||||
memcpy(buf, t.sn, n + 1);
|
||||
return 0;
|
||||
} else {
|
||||
return erange();
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -22,9 +22,14 @@
|
||||
/**
|
||||
* Checks if effective user can access path in particular ways.
|
||||
*
|
||||
* This is equivalent to saying:
|
||||
*
|
||||
* faccessat(AT_FDCWD, path, mode, 0);
|
||||
*
|
||||
* @param path is a filename or directory
|
||||
* @param mode can be R_OK, W_OK, X_OK, F_OK
|
||||
* @return 0 if ok, or -1 and sets errno
|
||||
* @return 0 if ok, or -1 w/ errno
|
||||
* @see faccessat() for further documentation
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int access(const char *path, int mode) {
|
||||
|
||||
+1
-3
@@ -32,12 +32,10 @@
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
unsigned alarm(unsigned seconds) {
|
||||
int rc;
|
||||
struct itimerval it;
|
||||
bzero(&it, sizeof(it));
|
||||
it.it_value.tv_sec = seconds;
|
||||
rc = setitimer(ITIMER_REAL, &it, &it);
|
||||
assert(rc != -1);
|
||||
_npassert(!setitimer(ITIMER_REAL, &it, &it));
|
||||
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
@@ -14,6 +15,10 @@ forceinline bool __asan_is_valid_timespec(const struct timespec *ts) {
|
||||
return zf;
|
||||
}
|
||||
|
||||
forceinline bool __asan_is_valid_timeval(const struct timeval *tv) {
|
||||
return __asan_is_valid_timespec((const struct timespec *)tv);
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
|
||||
#include "libc/thread/thread.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define BLOCK_CANCELLATIONS \
|
||||
do { \
|
||||
int _CancelState; \
|
||||
_CancelState = _pthread_block_cancellations()
|
||||
|
||||
#define ALLOW_CANCELLATIONS \
|
||||
_pthread_allow_cancellations(_CancelState); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
int _pthread_block_cancellations(void);
|
||||
void _pthread_allow_cancellations(int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_ */
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_H_
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define BLOCK_SIGNALS \
|
||||
do { \
|
||||
sigset_t _SigMask; \
|
||||
_SigMask = _sigblockall()
|
||||
|
||||
#define ALLOW_SIGNALS \
|
||||
_sigsetmask(_SigMask); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_H_ */
|
||||
+57
-57
@@ -35,11 +35,10 @@
|
||||
#define WIFCONTINUED(s) ((s) == 0xffff)
|
||||
#define WIFEXITED(s) (!WTERMSIG(s))
|
||||
#define WIFSIGNALED(s) ((0xffff & (s)) - 1u < 0xffu)
|
||||
#define WIFSTOPPED(s) \
|
||||
((short)(((0xffff & (unsigned)(s)) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) (127 & (s))
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
#define WIFSTOPPED(s) ((255 & (s)) == 127)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) (127 & (s))
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
@@ -65,14 +64,13 @@ char *ttyname(int);
|
||||
int access(const char *, int) dontthrow;
|
||||
int arch_prctl();
|
||||
int chdir(const char *);
|
||||
int chmod(const char *, uint32_t);
|
||||
int chown(const char *, uint32_t, uint32_t);
|
||||
int chmod(const char *, unsigned);
|
||||
int chown(const char *, unsigned, unsigned);
|
||||
int chroot(const char *);
|
||||
int clone(void *, void *, size_t, int, void *, int *, void *, int *);
|
||||
int close(int);
|
||||
int close_range(unsigned, unsigned, unsigned);
|
||||
int closefrom(int);
|
||||
int creat(const char *, uint32_t);
|
||||
int creat(const char *, unsigned);
|
||||
int dup(int);
|
||||
int dup2(int, int);
|
||||
int dup3(int, int, int);
|
||||
@@ -85,25 +83,22 @@ int execv(const char *, char *const[]);
|
||||
int execve(const char *, char *const[], char *const[]);
|
||||
int execvp(const char *, char *const[]);
|
||||
int execvpe(const char *, char *const[], char *const[]);
|
||||
int faccessat(int, const char *, int, uint32_t);
|
||||
int faccessat(int, const char *, int, int);
|
||||
int fadvise(int, uint64_t, uint64_t, int);
|
||||
int fchdir(int);
|
||||
int fchmod(int, uint32_t) dontthrow;
|
||||
int fchmodat(int, const char *, uint32_t, int);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, 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 filecmp(const char *, const char *);
|
||||
int fexecve(int, char *const[], char *const[]);
|
||||
int flock(int, int);
|
||||
int fork(void);
|
||||
int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
int getdents(unsigned, void *, unsigned, long *);
|
||||
int getdomainname(char *, size_t);
|
||||
int getegid(void) nosideeffect;
|
||||
int geteuid(void) nosideeffect;
|
||||
int getgid(void) nosideeffect;
|
||||
int getgroups(int, unsigned[]);
|
||||
int gethostname(char *, size_t);
|
||||
int getloadavg(double *, int);
|
||||
int getpgid(int) libcesque;
|
||||
@@ -111,35 +106,29 @@ int getpgrp(void) nosideeffect;
|
||||
int getpid(void) nosideeffect libcesque;
|
||||
int getppid(void);
|
||||
int getpriority(int, unsigned);
|
||||
int getresgid(uint32_t *, uint32_t *, uint32_t *);
|
||||
int getresuid(uint32_t *, uint32_t *, uint32_t *);
|
||||
int getresgid(unsigned *, unsigned *, unsigned *);
|
||||
int getresuid(unsigned *, unsigned *, unsigned *);
|
||||
int getsid(int) nosideeffect libcesque;
|
||||
int gettid(void) libcesque;
|
||||
int getuid(void) libcesque;
|
||||
int iopl(int);
|
||||
int ioprio_get(int, int);
|
||||
int ioprio_set(int, int, int);
|
||||
int issetugid(void);
|
||||
int kill(int, int);
|
||||
int killpg(int, int);
|
||||
int lchmod(const char *, uint32_t);
|
||||
int lchown(const char *, uint32_t, uint32_t);
|
||||
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 madvise(void *, uint64_t, int);
|
||||
int makedirs(const char *, unsigned);
|
||||
int memfd_create(const char *, unsigned int);
|
||||
int mincore(void *, size_t, unsigned char *);
|
||||
int mkdir(const char *, uint32_t);
|
||||
int mkdirat(int, const char *, uint32_t);
|
||||
int mkfifo(const char *, uint32_t);
|
||||
int mkfifoat(int, const char *, uint32_t);
|
||||
int mknod(const char *, uint32_t, uint64_t);
|
||||
int mknodat(int, const char *, int32_t, uint64_t);
|
||||
int mlock(const void *, size_t);
|
||||
int mlock2(const void *, size_t, int);
|
||||
int mlockall(int);
|
||||
int munlock(const void *, size_t);
|
||||
int munlockall(void);
|
||||
int mkdir(const char *, unsigned);
|
||||
int mkdirat(int, const char *, unsigned);
|
||||
int mkfifo(const char *, unsigned);
|
||||
int mkfifoat(int, const char *, unsigned);
|
||||
int mknod(const char *, unsigned, uint64_t);
|
||||
int mknodat(int, const char *, int, uint64_t);
|
||||
int nice(int);
|
||||
int open(const char *, int, ...);
|
||||
int openat(int, const char *, int, ...);
|
||||
@@ -149,7 +138,7 @@ int pipe(int[hasatleast 2]);
|
||||
int pipe2(int[hasatleast 2], int);
|
||||
int pivot_root(const char *, const char *);
|
||||
int pledge(const char *, const char *);
|
||||
int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||
int posix_fadvise(int, int64_t, int64_t, int);
|
||||
int posix_madvise(void *, uint64_t, int);
|
||||
int prctl(int, ...);
|
||||
int raise(int);
|
||||
@@ -161,35 +150,42 @@ int renameat2(long, const char *, long, const char *, int);
|
||||
int rmdir(const char *);
|
||||
int sched_yield(void);
|
||||
int seccomp(unsigned, unsigned, void *);
|
||||
int setegid(uint32_t);
|
||||
int seteuid(uint32_t);
|
||||
int setfsgid(int);
|
||||
int setfsuid(int);
|
||||
int setgid(int);
|
||||
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(uint32_t, uint32_t);
|
||||
int setresgid(uint32_t, uint32_t, uint32_t);
|
||||
int setresuid(uint32_t, uint32_t, uint32_t);
|
||||
int setreuid(uint32_t, uint32_t);
|
||||
int setregid(unsigned, unsigned);
|
||||
int setresgid(unsigned, unsigned, unsigned);
|
||||
int setresuid(unsigned, unsigned, unsigned);
|
||||
int setreuid(unsigned, unsigned);
|
||||
int setsid(void);
|
||||
int setuid(int);
|
||||
int setuid(unsigned);
|
||||
int sigignore(int);
|
||||
int siginterrupt(int, int);
|
||||
int symlink(const char *, const char *);
|
||||
int symlinkat(const char *, int, const char *);
|
||||
int sync_file_range(int, int64_t, int64_t, unsigned);
|
||||
int sys_iopl(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_ptrace(int, ...);
|
||||
int sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int tcsetpgrp(int, int32_t);
|
||||
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int tcgetpgrp(int);
|
||||
int tcsetpgrp(int, int);
|
||||
int tgkill(int, int, int);
|
||||
int tkill(int, int);
|
||||
int tmpfd(void);
|
||||
int touch(const char *, uint32_t);
|
||||
int truncate(const char *, uint64_t);
|
||||
int touch(const char *, unsigned);
|
||||
int truncate(const char *, int64_t);
|
||||
int ttyname_r(int, char *, size_t);
|
||||
int umask(int);
|
||||
int unlink(const char *);
|
||||
int unlink_s(const char **);
|
||||
int unlinkat(int, const char *, int);
|
||||
@@ -198,21 +194,25 @@ int usleep(unsigned);
|
||||
int vfork(void) returnstwice;
|
||||
int wait(int *);
|
||||
int waitpid(int, int *, int);
|
||||
int32_t tcgetpgrp(int);
|
||||
intptr_t syscall(int, ...);
|
||||
long ptrace(int, ...);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned);
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned);
|
||||
ssize_t getfiledescriptorsize(int);
|
||||
ssize_t lseek(int, int64_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 readansi(int, char *, size_t);
|
||||
ssize_t readlink(const char *, char *, size_t);
|
||||
ssize_t readlinkat(int, const char *, char *, size_t);
|
||||
ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned);
|
||||
ssize_t write(int, const void *, size_t);
|
||||
unsigned getegid(void) nosideeffect;
|
||||
unsigned geteuid(void) nosideeffect;
|
||||
unsigned getgid(void) nosideeffect;
|
||||
unsigned getuid(void) libcesque;
|
||||
unsigned umask(unsigned);
|
||||
void sync(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
||||
Loaded 100 of 3702 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user