Compare commits

...
223 Commits
Author SHA1 Message Date
Justine Tunney d0ad50f5ae Add multicast test that works on Linux
This test unfortunately doesn't work yet on non-Linux platforms, which
wasn't what I expected since the ip_mreq ABI is the same across all of
our supported platforms. There's also an automation issue due to using
INADDR_ANY since it causes popups on Windows.
2023-02-03 13:58:13 -08:00
Justine Tunney 4b8874ceb9 Make some simple fixes 2023-02-03 02:09:15 -08:00
Justine Tunney cf19e3e46a Fix SO_LINGER on Apple 2023-02-02 20:05:37 -08:00
Justine Tunney 1429a7b3ef Fix bug in ASAN reporting 2023-02-02 02:28:58 -08:00
Justine Tunney 7486a2cd51 Perform minor cleanups 2023-02-02 02:28:58 -08:00
Gavin Hayes fd0da9c0df Implement zipos mmap (#725) 2023-02-02 02:28:50 -08:00
Paul Kulchenko 6d36584ff2 Redbean lsqlite config addition (#724)
* Fix mislabeled constant in redbean SQLite code
* Simplify callback handling in redbean SQLite
* Add config options to redbean SQLite
* Update redbean SQLite API to return current error callback
2023-01-29 19:37:19 -08:00
James Hulce f422edaf15 FIx link in gensvg demo (#723)
Code link in the gensvg demo is broken, fix that
2023-01-28 09:12:13 -08:00
Justine Tunney 1473eafd1a Fix the build and introduce some APIs
The tcgetwinsize() and tcsetwinsize() APIs are now available. The
printargs.com example also now displays the baud rate.
2023-01-20 09:25:45 -08:00
Justine Tunney cac86197cb Add fix for Blink detection 2023-01-19 09:12:49 -08:00
Justine Tunney 006c44ff5d Update tests and CPU detection for Blink 2023-01-18 00:56:09 -08:00
Justine Tunney be3e109309 Fix build break 2023-01-08 15:35:08 -08:00
Justine Tunney 2bad436abf Return error on fopen(NULL)
https://sqlite.org/forum/forumpost/d1c96a9032e564f8
2023-01-08 15:17:44 -08:00
Justine Tunney 7ab4630cc9 Fix MODE=asan build regression 2023-01-08 05:47:18 -08:00
Justine Tunney 5dab97b6d4 Implement program for finding start of zip content 2023-01-06 19:55:00 -08:00
Justine Tunney b38a442386 Add ppc64le support and improve platform detection 2023-01-06 09:14:27 -08:00
Justine Tunney 0708310041 Update the blink binaries 2023-01-05 22:50:20 -08:00
Justine Tunney cd27a53345 Support aarch64, silicon, arm, i486, riscv64, mipsel, ppc and s390x
Your APE binaries will now run on eight hardware architectures. The
tradeoff is this change adds about 800kb of bloat to the executable
which to be fair is still more than half as small as Go hello world

Your APE shell script extracts an embedded build of Blink, based on
`$(uname -m)`. The Blink binaries are statically-linked (manylinux)
which means, they'll run on every distro's stock install, including
Apple M1's that haven't enabled Rosetta. Blink's emulation has been
designed to be nearly as fast as Rosetta, using a JIT technique for
faster startup time. Blink has also been tested more thoroughly, w/
emulating Cosmopolitan software, since we're the ones who wrote it.
2023-01-05 14:29:21 -08:00
Justine Tunney 416e173448 Improve the cosmocc toolchain
These changes were necessary to help Blink become buildable using
Cosmopolitan Libc.
2023-01-05 12:20:52 -08:00
Justine Tunney d73523864a Fix bugs with Redbean Fetch() uploading
This change makes Fetch() work correctly when large bodies are supplied,
or bodies containing NUL characters are supplied.

Fixes #573
2023-01-05 09:52:36 -08:00
Justine Tunney eb69a42863 Fix --strace crashing on MacOS and Windows 2023-01-04 06:46:37 -08:00
Justine Tunney 651826b660 Update assimilate to work with modern APE format 2023-01-04 06:34:48 -08:00
Justine Tunney 6dcdf91458 Add a turfwar hilbert decoration 2023-01-03 18:28:35 -08:00
Justine Tunney a6586cafb2 Retry SQLITE_BUSY when stepping in TurfWar 2023-01-03 06:10:39 -08:00
Justine Tunney e496ee7a80 Be less pushy about redbean ddos protection 2023-01-03 05:14:34 -08:00
Justine Tunney a4b6803556 Fix recursive locks when tid is huge
It turns out Linux may assign thread ids that are much larger than
previously thought. We now have fewer bits of depth so we can have
bigger tids.
2023-01-03 05:01:00 -08:00
Justine Tunney 9c72fef086 Remove affinity tuning from IPv4 Games 2023-01-03 04:48:01 -08:00
Justine Tunney 10d1c6da18 Support argv[0] munging on Windows 2023-01-03 03:22:40 -08:00
ahgamut 5ed84e04f8 remove libc/sock/if.h
libc/sock/if.h is removed because:

- it contained only IFNAMSIZ, which was also defined in
  libc/sock/struct/ifreq.h
- it was not included in any file EXCEPT libc/isystem/net/if.h, which
  also included the libc/sock/struct/ifreq.h

hence we remove this file, and move the IFNAMSIZ definition to
libc/sock/struct/ifreq.h which is included in isystem.
2023-01-01 16:51:00 -08:00
ahgamut 25fa6acc4d check existence of IFNAMSIZ
IFNAMSIZ is defined in:

- libc/sock/if.h
- libc/sock/struct/ifreq.h

we add a check in the latter to avoid a complaint when using the
amalgamated header.
2023-01-01 16:51:00 -08:00
Ronsor 9a46c5afc4 Add a new example showing how to use hiredis. 2023-01-01 16:30:10 -08:00
Ronsor 97ae5f7b1e Fix hiredis build 2023-01-01 16:30:10 -08:00
Ronsor 1c7c277432 Include a port of the hiredis library.
SSL support is not yet included; however, everything else works
perfectly fine.
2023-01-01 16:30:10 -08:00
Danny Robinson 70ca8c4016 Update redbean lsqlite definitions (#709) 2023-01-01 16:28:34 -08:00
tkchiaandtkchia 73507d5f4e Add some definitions for Linux frame buffer/console ioctl APIs (#712)
Co-authored-by: tkchia <[email protected]>
2023-01-01 16:28:03 -08:00
Ronsor d2f811eff3 Add support for the -i (include headers) and -d (POST data) options in curl.com (#708)
This commit also paves the way for initial IPv6 support in `curl.com` by specifying
`AF_UNSPEC` for the address family in the hints passed to `getaddrinfo()`.
2022-12-23 17:06:48 -08:00
Justine Tunney 2e5181666f Fix the build 2022-12-21 23:06:55 -08:00
Gavin Hayes 5c0ce6b83e Add note about APE loader and noexec mounts (#707) 2022-12-21 23:00:51 -08:00
Ronsor f6b3019796 Make curl example into a complete tool (#706)
You can now handily use `curl` with popen()/system() by
placing `STATIC_YOINK("_curl")` in your main source file.
2022-12-21 16:12:02 -08:00
Justine Tunney dd04aeba1c Increase stack size to 128k and guard size to 16k
This improves our compatibility with Apple M1.
2022-12-18 22:58:29 -08:00
Justine Tunney 57c0dcdc29 Decrease TurfWar background query intervals
The database is much larger than it was when we started, so these
background reporting queries have become much more expensive than
before. We also had someone make 750k claims in one day, and even
hundreds of thousands per hour, which broke our assumptions about
hourly / daily reports being cheap.
2022-12-18 02:23:12 -08:00
Justine Tunney 6d39c6f646 Have redbean avoid gzip when emulated without jit 2022-12-18 02:22:58 -08:00
Justine Tunney 5a3c646307 Fix sysinfo() totalram on XNU
HW_MEMSIZE is the 64-bit version of HW_PHYSMEM, which is inaccurate on
systems having more than 4gb of RAM.
2022-12-18 02:22:46 -08:00
tkchiaandtkchia 0da47c51de [metal] Allow programs larger than 440 KiB to run in bare metal mode (#685)
* [metal] Copy program pages to extended memory at startup
* [metal] Reclaim base memory pages for later app use
* [metal] Load program pages beyond 1st 440 KiB to extended memory

o//examples/hellolua.com now runs correctly under QEMU (in
legacy BIOS mode).

* [metal] Place GDT in read/write segment

The CPU absolutely needs to alter the GDT when loading the
task register (via ltr).  To account for this, I move the
GDT into a read/write data section.  There is still a "rump"
read-only GDT in the text section that is used by the real
mode bootloader.

We also delay the loading of the task register (ltr) until
after the IDT and TSS are finally set up.

* [metal] Get examples/vga2.c serial output working for UEFI boot
* [metal] Get examples/vga2.c VGA output working for UEFI boot
* [metal] Allow munmap() to reclaim dynamically allocated pages
* Place TLS sections right after .text, not after embedded zip file

Co-authored-by: tkchia <[email protected]>
2022-12-17 17:51:20 -08:00
Justine Tunney 120079b0a6 Remove evil constants from cosmopolitan.h
- `I` a.k.a. `_Complex_I` (fixes #705)
- `B0`, `B50`, etc. (fixes #403)
2022-12-17 00:42:45 -08:00
Justine Tunney 3da887c58f Introduce CPUID detection for Blink 2022-12-17 00:38:07 -08:00
Justine Tunney 4922bc4890 Fix SQLite3 build for Landlock Make 2022-12-11 14:49:53 -08:00
Justine Tunney ed161b240e Clean up some code 2022-12-11 14:30:59 -08:00
Justine Tunney 531bfbd61f Fix DNS resolution w/ commas in Windows Registry 2022-12-11 14:30:59 -08:00
Paul Kulchenko cd0b12ed1a Add diff and iterator to SQLite session (#700) 2022-11-28 13:40:04 -08:00
Paul Kulchenko 0dc0758574 Upgrade SQLite to 3.40 (#699) 2022-11-28 12:54:48 -08:00
Paul Kulchenko bcae817215 Update SQLite deserialize to allow resizing restored DB (#701)
Using either option (FREEONCLOSE or RESIZEABLE) requires using
sqlite3_malloc. Ref. #436
2022-11-28 12:53:20 -08:00
Justine Tunney b850b14300 Improve cosmocc / cosmoc++ toolchains
They'll now automatically create empty static archives for system
libraries that are provided by Cosmopolitan Libc. This helps make
configure scripts less confused. Musl does the same thing.
2022-11-14 13:45:57 -08:00
Justine Tunney a277170c9a Make kprintf_test resistant to limbo 2022-11-13 14:26:19 -08:00
Justine Tunney 711bd095db Import exuberant ctags 2022-11-13 13:26:28 -08:00
Justine Tunney d55b019284 Fix the build 2022-11-11 11:13:21 -08:00
Justine Tunney f2af97711b Make improvements
- Improve compatibility with Blink virtual machine
- Add non-POSIX APIs for joining threads and signal masks
- Never ever use anything except 32-bit integers for atomics
- Add some `#undef` statements to workaround `ctags` problems
2022-11-10 21:52:47 -08:00
Justine Tunney b46ac13504 Introduce new jartsr=' ape prefix
Files beginning with "MZqFpD" are Actually Portable Executables,
which have a printf statement in the first 4096 bytes with octal
codes that specify the ELF header. APE also specifies `jartsr='`
as an alternative prefix, intended for binaries that do not want
to be identified as Windows executables. Like the \177ELF magic,
all these prefixes decode as x86 jump instructions that could be
used for 16-bit bootloaders or 32-bit / 64-bit flat executables.
Most importantly they provide a fallback path for Thompson shell
copmatible command interpreters, which do not require a shebang,
e.g. bash, zsh, fish, bourne, almquist, etc. Please note that in
order to meet the requirements of POSIX.1, the single quote must
be followed by a newline character, before any null bytes occur.
See also: https://www.austingroupbugs.net/view.php?id=1250
2022-11-10 21:18:32 -08:00
Justine Tunney cee6871710 Make detached threads work better
This change adds a double linked list of threads, so that pthread_exit()
will know when it should call exit() from an orphaned child. This change
also improves ftrace and strace logging.
2022-11-09 03:58:57 -08:00
Justine Tunney b74d8c1acd Remove unnecessary STRACE() statement 2022-11-08 15:33:16 -08:00
Justine Tunney fc595a7111 Fix build
libc/integral changes aren't checked in the build dependency, due to
being explicitly listed in .UNVEIL, which is how this breakage ended
up accidentally slipping through the cracks.
2022-11-08 15:24:17 -08:00
Justine Tunney bf7843833f Rename hidden keyword to _Hide 2022-11-08 12:55:28 -08:00
Paul Kulchenko 251dcb07eb Add redbean sqlite session support (#680) 2022-11-08 12:53:37 -08:00
Justine Tunney b407327972 Make fixes and improvements
- clock_nanosleep() is now much faster on OpenBSD and NetBSD
- Thread joining is now much faster on NetBSD
- FreeBSD timestamps are now more accurate
- Thread spawning now goes faster on XNU
- Clean up the clone() code
2022-11-08 10:11:46 -08:00
Justine Tunney aee50b1327 Fix test breakage 2022-11-07 06:31:30 -08:00
Justine Tunney 4de2cf34e6 Allow HTTP range past EOF
Fixes #683
2022-11-07 05:52:24 -08:00
Justine Tunney 52f1db7220 Release Cosmopolitan v2.2 2022-11-07 02:29:47 -08:00
Justine Tunney c995838e5c Make improvements
- Clean up sigaction() code
- Add a port scanner example
- Introduce a ParseCidr() API
- Clean up our futex abstraction code
- Fix a harmless integer overflow in ParseIp()
- Use kernel semaphores on NetBSD to make threads much faster
2022-11-07 02:26:06 -08:00
Justine Tunney 539bddce8c Fix regression in documentation page 2022-11-06 01:16:29 -07:00
Justine Tunney 002df0f16c Fix regression in MODE=asan build 2022-11-06 01:05:13 -07:00
Justine Tunney be16bcdcd3 Fix missing Makefile dependency 2022-11-06 01:01:34 -07:00
tkchia cb9a0466f1 Work towards zipos / open(argv[0]) on metal (#667) 2022-11-06 00:29:47 -07:00
Danny Robinson 543c93f623 bestline keybindings and redbean definitions (#678)
* Add ctrl-left/right keys to bestline
* Update redbean API definitions
2022-11-06 00:28:08 -07:00
Justine Tunney 3f0bcdc3ef Improve cancellations, randomness, and time
- Exhaustively document cancellation points
- Rename SIGCANCEL to SIGTHR just like BSDs
- Further improve POSIX thread cancellations
- Ensure asynchronous cancellations work correctly
- Elevate the quality of getrandom() and getentropy()
- Make futexes cancel correctly on OpenBSD 6.x and 7.x
- Add reboot.com and shutdown.com to examples directory
- Remove underscore prefix from awesome timespec_*() APIs
- Create assertions that help verify our cancellation points
- Remove bad timespec APIs (cmp generalizes eq/ne/gt/gte/lt/lte)
2022-11-05 23:45:32 -07:00
Justine Tunney 0d7c265392 Fix backtraces on cancellation points 2022-11-04 20:22:13 -07:00
Justine Tunney 022536cab6 Make futexes cancellable by pthreads 2022-11-04 18:36:34 -07:00
Justine Tunney 2278327eba Implement support for POSIX thread cancellations
This change makes some miracle modifications to the System Five system
call support, which lets us have safe, correct, and atomic handling of
thread cancellations. It all turned out to be cheaper than anticipated
because it wasn't necessary to modify the system call veneers. We were
able to encode the cancellability of each system call into the magnums
found in libc/sysv/syscalls.sh. Since cancellations are so waq, we are
also supporting a lovely Musl Libc mask feature for raising ECANCELED.
2022-11-04 01:04:43 -07:00
Justine Tunney 37d40e087f Ignore SIGSYS on BSD by default 2022-11-03 09:32:12 -07:00
Justine Tunney 179e048bba Make some small fixes to recent changes 2022-11-03 05:45:33 -07:00
Justine Tunney c2590cf7a0 Make cosmo.ftrace() in Python easier to use 2022-11-03 01:12:25 -07:00
Justine Tunney 89d1e5b8f2 Rearrange code and make a faster sha256sum program 2022-11-02 23:19:16 -07:00
Justine Tunney 5e60e5ad10 Release redbean v2.2 2022-11-02 09:52:54 -07:00
Justine Tunney 6b06a8176d Fix some glitches in redbean
This change includes a fix to Fetch() where an out of bounds memory read
could happen, when the reverse proxied endpoint omits the content-length
header. This caused a bunch of NUL chars to appear on TurfWar's /statusz
since it wouldn't actually overrun the buffer, and if it did it would've
been caught by MODE=asan builds.
2022-11-02 09:46:34 -07:00
Justine Tunney 14d036b68d Add WSL to test fleet
All tests pass now under WSL2. They should pass under WSL1 too, but only
WSL2 is integrated into the test fleet right now. This change also fills
in some gaps in the error numbers.

Fixes #665
2022-11-02 06:49:42 -07:00
Justine Tunney fae0c0286f Workaround WSL not supporting x87 in ucontext_t 2022-11-02 03:20:39 -07:00
Justine Tunney d6ff4c754e Workaround WSL misconfiguring the x87 FPU 2022-11-02 02:17:14 -07:00
Justine Tunney f44d88707e Workaround sendfile() bug in WSL 2022-11-02 02:17:03 -07:00
Justine Tunney fc96af058b Workaround MAP_GROWSDOWN unavailability on WSL 2022-11-02 01:38:06 -07:00
Justine Tunney bd6069deb5 Remove old code from Landlock Make 2022-11-02 00:55:05 -07:00
Justine Tunney e9735a7738 Release landlock make 1.5 2022-11-01 23:52:38 -07:00
Stephen M. Cameron 0ea10c8631 Add useconds_t type to weirdtypes.h 2022-11-01 23:28:26 -07:00
Justine Tunney e522aa3a07 Make more threading improvements
- ASAN memory morgue is now lockless
- Make C11 atomics header more portable
- Rewrote pthread keys support to be lockless
- Simplify Python's unicode table unpacking code
- Make crash report write(2) closer to being atomic
- Make it possible to strace/ftrace a single thread
- ASAN now checks nul-terminated strings fast and properly
- Windows fork() now restores TLS memory of calling thread
2022-11-01 23:28:26 -07:00
Paul Kulchenko d7b88734cd Make redbean compress w/o explicit content-type (#671) 2022-11-01 23:15:20 -07:00
Gavin Hayes da8f5009fd Make Windows fcntl() and lseek() fixes (#668)
* F_SETFD should always return 0 on success
* F_SETFL is not implemented on nt
* nt lseek, error with ESPIPE when attempting on socket
2022-11-01 23:14:14 -07:00
mattx ef9776755e blackholed: allow changing iptables chain (#670)
* Make blackholed use its own chain

This makes blackholed interfere less with any existing iptables raw table configurations.

* Allow specifying iptables chain at runtime

blackholed will now insert blocks to the PREROUTING chain by default,
with a runtime switch to change it to another chain
2022-10-20 10:19:27 -07:00
Justine Tunney da336b3ea8 Make some more fixes to prod 2022-10-19 13:10:24 -07:00
Justine Tunney 69bee64a59 Make some last minute production changes 2022-10-19 10:00:29 -07:00
Justine Tunney f7ff77d865 Make fixes and improvements
- Invent iso8601us() for faster timestamps
- Improve --strace descriptions of sigset_t
- Rebuild the Landlock Make bootstrap binary
- Introduce MODE=sysv for non-Windows builds
- Permit OFD fcntl() locks under pledge(flock)
- redbean can now protect your kernel from ddos
- Have vfork() fallback to sys_fork() not fork()
- Change kmalloc() to not die when out of memory
- Improve documentation for some termios functions
- Rewrite putenv() and friends to conform to POSIX
- Fix linenoise + strace verbosity issue on Windows
- Fix regressions in our ability to show backtraces
- Change redbean SetHeader() to no-op if value is nil
- Improve fcntl() so SQLite locks work in non-WAL mode
- Remove some unnecessary work during fork() on Windows
- Create redbean-based SSL reverse proxy for IPv4 TurfWar
- Fix ape/apeinstall.sh warning when using non-bash shells
- Add ProgramTrustedIp(), and IsTrustedIp() APIs to redbean
- Support $PWD, $UID, $GID, and $EUID in command interpreter
- Introduce experimental JTqFpD APE prefix for non-Windows builds
- Invent blackhole daemon for firewalling IP addresses via UNIX named socket
- Add ProgramTokenBucket(), AcquireToken(), and CountTokens() APIs to redbean
2022-10-19 07:19:19 -07:00
Justine Tunney 648bf6555c Reimport zip into third party 2022-10-16 13:39:41 -07:00
Justine Tunney 60cb435cb4 Implement pthread_atfork()
If threads are being used, then fork() will now acquire and release and
runtime locks so that fork() may be safely used from threads. This also
makes vfork() thread safe, because pthread mutexes will do nothing when
the process is a child of vfork(). More torture tests have been written
to confirm this all works like a charm. Additionally:

- Invent hexpcpy() api
- Rename nsync_malloc_() to kmalloc()
- Complete posix named semaphore implementation
- Make pthread_create() asynchronous signal safe
- Add rm, rmdir, and touch to command interpreter builtins
- Invent sigisprecious() and modify sigset functions to use it
- Add unit tests for posix_spawn() attributes and fix its bugs

One unresolved problem is the reclaiming of *NSYNC waiter memory in the
forked child processes, within apps which have threads waiting on locks
2022-10-16 12:25:13 -07:00
Justine Tunney 64c284003d Fix MODE=opt build 2022-10-14 16:49:16 -07:00
Justine Tunney 3d2d04b25e Make cli commands yoinkable into cosmo shell
This lets our system() and popen() commands function sort of like
BusyBox and ToyBox. By default the Cosmopolitan Shell is lightweight.
But if you use STATIC_YOINK then you can pull the individual commands
you want into the linkage, and they'll be included in a single binary.
For example the demo binary embeds `tr` and `sed` and ends up ~140kb.
2022-10-14 16:37:29 -07:00
Justine Tunney 5af19b7eed Make some foss compatibility improvements 2022-10-14 13:59:34 -07:00
Justine Tunney 8111462789 Add posix semaphores support
There's still some bugs to work out on Windows and OpenBSD.
2022-10-14 09:21:02 -07:00
Justine Tunney f52f65b2e3 Make system() and popen() thread safe 2022-10-13 15:54:05 -07:00
Justine Tunney 997ce29ddc Elevate Windows production worthiness
- SQLite file locking now works on Windows
- SQLite will now use fdatasync() on non-Apple platforms
- Fix Ctrl-C handler on Windows to not crash with TLS
- Signals now work in multithreaded apps on Windows
- fcntl() will now accurately report EINVAL errors
- fcntl() now has excellent --strace logging
- Token bucket replenish now go 100x faster
- *NSYNC cancellations now work on Windows
- Support closefrom() on NetBSD
2022-10-13 13:44:41 -07:00
tkchia d38700687a [metal] Allow more fine-grained control over page permissions (#663)
- use PAGE_RSRV bit (originally only for blinkenlights),
  rather than PAGE_V bit, to indicate that a virtual address
  page has been reserved — this should allow a program to
  create & reserve inaccessible "guard pages"
- mark page table entries for non-code pages with PAGE_XD bit,
  which should be supported on (circa) post-2004 x86-64 CPUs
2022-10-12 11:07:11 -07:00
Justine Tunney 0f89140882 Further improve cocmd interpreter 2022-10-12 10:44:54 -07:00
Justine Tunney 0cee831da3 Revamp posix_spawn() implementation 2022-10-12 05:26:58 -07:00
Justine Tunney b41f91c658 Greatly expand system() shell code features
The cosmopolitan command interpreter now has 13 builtin commands,
variable support, support for ; / && / || syntax, asynchronous support,
and plenty of unit tests with bug fixes.

This change fixes a bug in posix_spawn() with null envp arg. strace
logging now uses atomic writes for scatter functions. Breaking change
renaming GetCpuCount() to _getcpucount(). TurfWar is now updated to use
the new token bucket algorithm. WIN32 affinity masks now inherit across
fork() and execve().
2022-10-11 21:30:31 -07:00
Justine Tunney e7329b7cba Implement atomic swar token bucket library 2022-10-11 21:22:04 -07:00
Justine Tunney c19ac8729d Reinvent the classic unix wall command 2022-10-11 21:22:03 -07:00
Connor 9d2f993364 Fix make sandboxing logic for .STRICT mode (#661)
Patch segfaults and handle the `.STRICT = 0` case.
2022-10-11 21:16:03 -07:00
tkchia 31dab8a75d [metal] Fix bug: do not initialize IDT & TSS if unneeded (#654)
libc/intrin/interrupts.S should not be linked in unless
an IDT (or TSS) is explicitly requested somewhere (i.e.
it should probably not be a mandatory module).
2022-10-10 20:54:46 -07:00
tkchiaandtkchia 7a06760e6f Rename LINUX to _HOSTLINUX etc. to reduce clashes (#655)
Co-authored-by: tkchia <[email protected]>
2022-10-10 20:31:25 -07:00
Connor 9209ea63a7 Integrate upstream dash changes into unbourne shell (#656) 2022-10-10 20:29:28 -07:00
Malcolm Seyd 84b9b8ed87 Fix ParseHttpMessage failing to store >2 repeatable headers (#657) 2022-10-10 20:17:17 -07:00
Justine Tunney e557058ac8 Improve cosmo's conformance to libc-test
This change addresses various open source compatibility issues, so that
we pass 313/411 of the tests in https://github.com/jart/libc-test where
earlier today we were passing about 30/411 of them, due to header toil.
Please note that Glibc only passes 341/411 so 313 today is pretty good!

- Make the conformance of libc/isystem/ headers nearly perfect
- Import more of the remaining math library routines from Musl
- Fix inconsistencies with type signatures of calls like umask
- Write tests for getpriority/setpriority which work great now
- conform to `struct sockaddr *` on remaining socket functions
- Import a bunch of uninteresting stdlib functions e.g. rand48
- Introduce readdir_r, scandir, pthread_kill, sigsetjmp, etc..

Follow the instructions in our `tool/scripts/cosmocc` toolchain to run
these tests yourself. You use `make CC=cosmocc` on the test repository
2022-10-10 17:52:41 -07:00
Justine Tunney 467a332e38 Introduce sigtimedwait() and sigwaitinfo()
This change also invents sigcountset() and strsignal_r() and improves
the quality of siginfo_t handling.
2022-10-10 07:39:44 -07:00
Justine Tunney 7ae556463a Rename rand64() to _rand64() 2022-10-10 04:12:06 -07:00
Justine Tunney c424352a0a Disable make sandobxing unless .STRICT=1
This change makes Landlock Make backwards compatible.
2022-10-10 03:49:58 -07:00
Justine Tunney d5910e2673 Fix bugs and make code tinier
- Fixed bug where stdio eof wasn't being sticky
- Fixed bug where fseeko() wasn't clearing eof state
- Removed assert() usage from libc favoring _unassert() / _npassert()
2022-10-09 23:21:34 -07:00
Justine Tunney 9b7c8db846 Perform some code maintenance
- Change IDT code so kprintf() isn't mandatory dependency
- Document current intentions around pthread_cancel()
- Make _npassert() an _unassert() in MODE=tiny
2022-10-09 13:00:46 -07:00
Justine Tunney 4a6fd3d910 Make more improvements to threading support
- fix rare thread exit race condition on openbsd
- pthread_getattr_np() now supplies detached status
- child threads may now pthread_join() the main thread
- introduce sigandset(), sigorset(), and sigisemptyset()
- introduce pthread_cleanup_push() and pthread_cleanup_pop()
2022-10-09 00:08:47 -07:00
Justine Tunney 38df0a4186 Release Cosmpolitan 2.1.1 2022-10-08 09:17:13 -07:00
Justine Tunney 1c0adb556d Release redbean v2.1 2022-10-08 09:03:51 -07:00
Justine Tunney 8aca94f951 Add shared memory hit counter example to redbean 2022-10-08 08:39:13 -07:00
Justine Tunney 38e3ab57a6 Add the TurfWar schema 2022-10-08 03:23:21 -07:00
Justine Tunney 672ccda37c Clean up some sleep code 2022-10-08 03:00:48 -07:00
Justine Tunney 9849b4c7ba Add *NSYNC unit test suite
This change also fixes the clock_nanosleep() api and polyfills futexes
on Windows, Mac, and NetBSD using exponential backoff.
2022-10-07 21:34:15 -07:00
tkchia 3421b9a580 [metal] Push forward timing of VGA TTY initialization (#653) 2022-10-07 17:10:28 -07:00
Justine Tunney 29d695f4c9 Make unbing() not need initialization 2022-10-07 14:56:02 -07:00
Justine Tunney 7d6835c0dd Release pledge v1.8 2022-10-07 03:41:50 -07:00
Justine Tunney 05197afca2 Do some work on TurfWar 2022-10-07 03:11:07 -07:00
tkchia bc353f454b Fix sys_mmap_metal() for non-MAP_FIXED case (#651)
- correctly check that virtual region we want to use is
  unmapped, rather than accidentally clobbering existing pages
- avoid placing mmap'd memory at null virtual address
2022-10-06 16:27:52 -07:00
Danny Robinson 7bc24888fe Update redbean api definitions (#652) 2022-10-06 16:27:23 -07:00
Justine Tunney 59ac141e49 Improve the affinity system calls 2022-10-06 15:08:29 -07:00
Justine Tunney 60b68d7152 Fix naming for redbean shared memory atomics 2022-10-06 09:41:22 -07:00
Justine Tunney a5b483f2d4 Make some quick fixes 2022-10-06 06:36:46 -07:00
tkchia d3efa47f81 Show "screen of death" on VGA console upon program crash (#650)
* [metal] Refactoring: separate out sys_writev_vga() and _vga_init() modules

* [metal] Read VGA info from BDA before long mode entry, not after

If using a pre-existing VGA text console, the VGA initialization
code now retrieves the cursor position & character height from
the BIOS data area while still in real mode — rather than
reading from the BIOS data area only after entering long mode.

(This should help make the code more correct, if Cosmopolitan
were to support UEFI graphics output in the future.  If the
program were booted via UEFI, then the long mode IsMetal()
code would still be activated, but the BIOS data area might
not have been initialized in that case.)

This change also means that there are now a few more fields
in the `struct mman`.

* [metal] VGA console can now show "screen of death" upon a crash

There is now a new function _klog_vga(), which can be called
by kprintf() to output system messages — e.g. information about
CPU exceptions — on the VGA screen.

* [metal] CPU exception handler now dumps cr2 value
* [metal] Add demo of program crash reporting w/ bare metal VGA TTY
* [metal] Reduce size of "screen of death" code
2022-10-06 05:36:15 -07:00
Justine Tunney 7822917fc2 Add shared memory apis to redbean
You can now do things like implement mutexes using futexes in your
redbean lua code. This provides the fastest possible inter-process
communication for your production systems when SQLite alone as ipc
or things like pipes aren't sufficient.
2022-10-06 04:55:26 -07:00
Justine Tunney 81ee11a16e Fix futimes() regression
Fixes #647
2022-10-05 19:25:07 -07:00
Hugues Morisset f155205eb0 Add imaxdiv, wcscoll, getdtablesize (#639) 2022-10-05 07:14:58 -07:00
Gavin Hayes e46ef487a8 Add utime to utime.h (#648) 2022-10-05 07:13:23 -07:00
Daniel Oltmanns afc07b9339 Proof of concept of sqlite serialization (#436)
* Proof of concept of sqlite serialization

This is a minimal proof of concept in order to show that it is easily possible to store the sqlite database within the zip file itself not requiring creating an external file first. Changes include compiling the sqlite library with the serialization flag, adding serialize/deserialize to the lua sqlite library and demonstrating the work via the redbean demo.

* Change demo for sqlite serialization

As explained in https://github.com/jart/cosmopolitan/pull/436#issuecomment-1164706893 the original use case is not possible with sqlite serialization, as an in-memory database cannot be shared across multiple processes. Thereby, this use case simply creates a backup of the in-memory database created in '.init.lua' and loads it to do a query.

* Fix sqlite3_deserialize parameters

The call to the sqlite3 library for the deserilization wasn't fully correct. This should fix the size parameters.
2022-10-05 07:09:53 -07:00
tkchia edb8fef06c Add basic character output for VGA graphics mode console (#649)
* Test output of colors for VGA graphics modes in examples/vga.c
* [metal] Character output in VGA graphics modes is mostly working
* [metal] Mention magic key to switch video mode, at bootup
2022-10-05 06:46:50 -07:00
Justine Tunney b75a4654cf Introduce clock_nanosleep() 2022-10-05 06:37:15 -07:00
Justine Tunney fe3216e961 Perform some code cleanup 2022-10-04 23:32:16 -07:00
Justine Tunney 174d288e66 Tune claim SQL query 2022-10-04 10:22:08 -07:00
Justine Tunney 9f9b240f3d Make HTTP message parsing a little faster
ParseHttpMessage() now does a better job avoiding malloc() calls and
headers commonly sent by CloudFlare can now be consulted in constant
time using our hard-coded perfect hash table.  This increases /claim
performance from 321k to 337k qps which is 5% faster.
2022-10-04 06:37:46 -07:00
Justine Tunney 726f04e8aa Further enhance IPv4 TurfWar server
- We now vary `/claim` responses based on the `Accept` header
- Remove xasprintf() call to boost `/claim` perf to 321k qps!
2022-10-04 05:27:36 -07:00
Justine Tunney 556697cbd8 Fix MODE=dbg build 2022-10-03 22:58:00 -07:00
Justine Tunney 3ee3736a01 Put finishing touches on turfwar http server
- Shutdown process now has optimal cancellation latency
- Fairer techniques for shedding connections under load
- We no longer need to call poll() which is now removed
2022-10-03 21:50:00 -07:00
Justine Tunney 01bd7d1008 Update a few remaining zlib source files 2022-10-03 19:24:02 -07:00
Justine Tunney 32321ab1e9 Further improve ipv4.games server 2022-10-03 16:00:04 -07:00
Justine Tunney 3b4fcd8575 Fix corner case in Linux stack mappings
We need to make sure no existing mappings exist between the
MAP_GROWSDOWN page and the guard page, since otherwise it's
not going to be able to grow down thus causing difficult to
troubleshoot failures.
2022-10-03 13:43:52 -07:00
Justine Tunney 6ba3b448f3 Fix file descriptor leak in turfwar.c 2022-10-03 08:34:04 -07:00
Justine Tunney 91e167caaf Rewrite IPv4 Turf War backend
It can now handle 240k SQLite write QPS at 3ms 99 percentile latency.
We're still working out the kinks since it's brand new. But we've got
this running in production already!
2022-10-03 08:23:54 -07:00
Justine Tunney ccbae7799e Improve docs of more system calls
This change also found a few POSIX compliance bugs with errnos. Another
bug was discovered where, on Windows, pread() and pwrite() could modify
the file position in cases where ReadFile() returned an error e.g. when
seeking past the end of file. We also have more tests!
2022-10-02 22:14:33 -07:00
Justine Tunney af24c19db3 Support whitespace after cocmd output redirection 2022-10-02 21:55:16 -07:00
Justine Tunney 950a1b310b Embed cocmd.com interpreter for system() / open()
This change lets you use system() in an easier and portable way. The
problem with the call in the past has always been that bourne and
cmd.com on Windows have less than nothing in common, so pretty much the
only command system() could be used for across platforms was maybe echo.
cmd.exe is also a security liability due to its escaping rules.

Since cocmd.com implements 85% of what we need from bourne, in a really
tiny way, it makes perfect sense to be embedded in these functionss. We
get a huge performance boost too.

Fixes #644
2022-10-02 15:29:57 -07:00
Justine Tunney daca5499b9 Add some tests for execve() 2022-10-02 14:58:14 -07:00
Danny Robinson 2526a9b8c7 Fix re.NOSUB memory error (#645) 2022-10-02 12:49:23 -07:00
Justine Tunney 7549a5755e Support futexes on FreeBSD 2022-10-02 11:57:13 -07:00
Justine Tunney 795d295590 Tune GitHub Actions to use APE loader 2022-10-02 10:20:08 -07:00
Justine Tunney 3f3cb0650b Have execve() escape double quotes in cmd.exe's preferred style
This makes it possible for us to use system() and popen() with paths
that redirect to filenames that contain spaces, e.g.

    system("echo.com hello >\"hello there.txt\"")

It's difficult to solve this problem, because WIN32 only allows passing
one single argument when launching programs and each program is allowed
to tokenize that however it wants. Most software follows the convention
of cmd.exe which is poorly documented and positively byzantine.

In the future we're going to solve this by not using cmd.exe at all and
instead embedding the cocmd.com interpreter into the system() function.
In the meantime, our documentation has been updated to help recalibrate
any expectation the user might hold regarding the security of using the
Windows command interpreter.

Fixes #644
2022-10-02 09:15:46 -07:00
Justine Tunney acd8900071 Add fexecve() and map O_EXEC to O_PATH on Linux 2022-10-02 09:15:46 -07:00
Justine Tunney 6c60793f3a Add better fix for Windows fork+strace TLS crashes 2022-10-02 09:15:46 -07:00
Justine Tunney ad97775370 Improve system call documentation
This change also introduces partial faccessat() support for zipos and
makes some slight breaking changes in errno results. close() is fixed
to use `EBADF` rather than `EINVAL` and we're now using `ENOTSUP` not
`EOPNOTSUPP` to indicate that zipos doesn't support a system call yet
2022-10-02 09:15:46 -07:00
Justine Tunney 0b5f84dd20 Introduce double quote support in cocmd.com shell 2022-10-02 09:15:46 -07:00
Justine Tunney 27b5deefb1 Introduce testlib_extract() helper 2022-10-02 09:15:46 -07:00
tkchia ecb2ef7c39 Start exploring graphical video modes for VGA console (#637) 2022-10-02 01:50:16 -07:00
Hugues Morisset 304cf8869c Fix wcsdup malloc size (#641)
Other wcs* function expect a full sizeof(wchar_t) NUL char at the end
of the string.
2022-10-02 00:47:05 -07:00
tkchia 3e0ddf70e9 Make shell script magic less prone to breakage (#643)
The metal boot sector code was wrapped in a single-quoted
string, like so:

    MZqFpD='
    ...MZ HEADER...
    ...E_LFANEW...
    ...BIOS BOOT SECTOR...'

This might break the shell code loader if the boot sector code
contains a 0x27 (single quote) byte.  This patch wraps the
boot sector code in a here-document instead:

    MZqFpD='
    ...MZ HEADER...' <<'@'
    ...E_LFANEW...
    ...BIOS BOOT SECTOR...
    @

This is harder to break — when interpreted as a shell script,
the code can only accidentally terminate the here-document
if there is a "\n@\n" sequence inside the BIOS boot portion.
2022-10-02 00:45:25 -07:00
Justine Tunney 5005f2e446 Rewrite brk() and sbrk()
This change reduces the .bss memory requirement for all executables by
O(64kb). The brk system calls are now fully tested and figured out and
might be useful for tiny programs that only target System Five.
2022-10-01 23:11:56 -07:00
tkchia bc8532688b Enable CPU exception handling w/ IDT & TSS (#640) 2022-09-29 14:43:08 -07:00
Justine Tunney 09811e739f Add Wasmer to Special Thanks 2022-09-27 19:00:11 -07:00
Justine Tunney 24988f2351 Add Rob Figueiredo to Special Thanks 2022-09-27 18:17:22 -07:00
Justine Tunney b46f763ee7 Permit multiple certs with same common name
This is needed to support Cloudflare interop.
2022-09-27 18:17:04 -07:00
Gavin Hayes 87708c5d6e Change accept type to struct sockaddr * (#630) 2022-09-20 07:49:16 -07:00
Justine Tunney 8c2bf341e9 Release Cosmopolitan 2.1 2022-09-20 05:19:30 -07:00
Justine Tunney 6cc9e08f1b Introduce cosmocc and cosmoc++ toolchain commands 2022-09-20 04:34:03 -07:00
Justine Tunney bfb85fe6d0 Remove a bunch of stuff that shouldn't be in docs 2022-09-20 02:57:46 -07:00
Justine Tunney 2cc1d5ac4c Improve redbean method=get parameter handling 2022-09-19 20:04:39 -07:00
Justine Tunney 6e582d245b Improve some timespec functions 2022-09-19 16:13:37 -07:00
Justine Tunney 2395a9eced Work around copy_file_range() GitHub Actions issue 2022-09-19 16:12:56 -07:00
Justine Tunney 0060940d84 Fix MODE=opt build 2022-09-19 15:43:52 -07:00
Justine Tunney 1ea01fc905 Fix pledge() thread killing semantics
- tkill(tid, sig) should be allowed by stdio
- tgkill(getpid(), tid, sig) should be allowed by stdio

Fixes #628
2022-09-19 15:34:11 -07:00
Justine Tunney c7a8cd21e9 Improve system call wrappers
This change improves copy_file_range(), sendfile(), splice(), openpty(),
closefrom(), close_range(), fadvise() and posix_fadvise() in addition to
writing tests that confirm things like errno and seeking behavior across
platforms. We now less aggressively polyfill behavior with some of these
functions when the platform support isn't available. Please see:

https://justine.lol/cosmopolitan/functions.html
2022-09-19 15:06:25 -07:00
Justine Tunney 224c12f54d Make zlib go faster 2022-09-18 06:30:45 -07:00
Justine Tunney be29b709b7 Fix pledge.com interop with Go DNS
Based on a pure analysis of the Go source code, it wants:

- SOL_SOCKET + SO_BROADCAST
- IPPROTO_IPV6 + IPV6_V6ONLY

Fixes #627
2022-09-18 03:56:52 -07:00
Justine Tunney e14ae1642e Fix MbedTLS Cloudflare interop in MODE=tiny 2022-09-18 03:52:09 -07:00
Justine Tunney 40991ec992 Fix getgroups / setgroups tests across platforms
See #619
2022-09-18 03:18:38 -07:00
Justine Tunney 97bb5a3a80 Fix MODE=dbg build 2022-09-18 03:16:14 -07:00
Justine Tunney bc3d84341d Fix redbean unix.nanosleep() documentation 2022-09-18 03:02:26 -07:00
tkchia c937fbb222 [metal] Export struct offsets from C code (#625)
Rather than computing them by hand.
2022-09-18 02:54:55 -07:00
tkchia cdf9e8c8a3 Bare metal VGA: fix mapping of ECMA-48 colors to VGA colors (#622)
See https://github.com/jart/cosmopolitan/pull/613#issuecomment-1247490693
2022-09-18 02:50:00 -07:00
Gavin Hayes 4c40c500b8 Add getgroups and setgroups (#619) 2022-09-18 02:48:53 -07:00
Justine Tunney 3665232d66 Release redbean 2.0.19 2022-09-17 02:18:19 -07:00
Justine Tunney 775944a2d0 Fix important bugs in redbean
This change upgrades to the latest Chromium Zlib, fixes bugs in redbean,
and introduces better support for reverse proxies like Cloudflare. This
change improves the security of redbean and it's recommended that users
upgrade to the release that'll follow. This change also updates the docs
to clarify how to use the security tools redbean provides e.g. pledge(),
unveil(), and the MODE=asan builds which improve memory safety.
2022-09-17 02:18:06 -07:00
Justine Tunney 994e1f4386 Improve pthread_join()
Since we're now on Windows 8, we can have clone() work as advertised on
Windows, where it sends a futex wake to the child tid. It's also likely
we no longer need to work around thread flakes on OpenBSD, in _wait0().
2022-09-16 14:02:06 -07:00
tkchia 3733b43a8f Bare metal: fix corner case in __normalize_e820( ) (#624)
See https://github.com/jart/cosmopolitan/pull/609#issuecomment-1247083243
2022-09-15 21:09:29 -07:00
Justine Tunney 134ffee519 Change support vector to Windows 8+
Doing this makes binaries tinier, since we don't need to have all the
extra code for supporting a 32-bit address space. It also benefits us
because we're able to use WIN32 futexes, which makes locking simpler.

b69f3d2488 is what officially ended our
Windows 7 support. This change is merely a formalization. You can use
old versions of Cosmo now and forevermore if you need Windows 7 since
our repository is hermetic and vendors all its dependencies.

Won't fix #617
2022-09-15 03:55:05 -07:00
Connor 6c90f830d9 Retain DWARF 5 sections for line numbers (#618)
Fixes #594
2022-09-14 23:03:49 -07:00
Gavin Hayes 14731d61fa fix MODE=dbg python build (#620) 2022-09-14 22:53:44 -07:00
Paul Kulchenko 418bcb39af Allow optional double quotes in dd parameters on macOS (#621) 2022-09-14 22:53:20 -07:00
Justine Tunney 3f49889841 Make important improvements
- Fix preadv() and pwritev() for old distros
- Introduce _npassert() and _unassert() macros
- Prove that file locks work properly on Windows
- Support fcntl(F_DUPFD_CLOEXEC) on more systems
2022-09-14 22:39:08 -07:00
Justine Tunney 1ad2f530f9 Add script.com and whois.com courtesy of FreeBSD 2022-09-13 20:26:13 -07:00
Justine Tunney 654ceaba7d Clean up threading code some more 2022-09-13 20:17:34 -07:00
tkchia 6a3330d7c9 VGA tty initialization should not run outside of bare metal mode (#614) 2022-09-13 15:27:19 -07:00
tkchia 945699694e Bare metal VGA: clarify code comments (#616) 2022-09-13 15:26:33 -07:00
Justine Tunney aab4ee4072 Add sys_ prefix to unwrapped system calls
This change also implements getlogin() and getlogin_r().
2022-09-13 11:20:35 -07:00
Justine Tunney 8f5678882d Make dos errno multimapping linkage tinier
640 bytes for old kDos2Errno table
182 bytes for new kDos2Errno under hello2.com (MODE=fastbuild)
122 bytes for new kDos2Errno under hello2.com (MODE=tiny)
2022-09-13 06:25:50 -07:00
Justine Tunney 9fa6725067 Fix bug with sendfile() on XNU 2022-09-13 04:32:29 -07:00
Justine Tunney 06f9a5b627 Get repository to build with GCC 11
See #594
2022-09-13 04:14:55 -07:00
Justine Tunney 446a1f7c5a Fix the build 2022-09-13 02:28:07 -07:00
tkchiaandtkchia df08b541af Bare metal VGA: implement "status report" escape codes (#613)
* Bare metal VGA: implement "status report" escape codes
* Minor fix to pseudoteletypewriter code

Co-authored-by: tkchia <[email protected]>
2022-09-13 02:14:10 -07:00
tkchiaandtkchia e0fabd1d49 [WIP] Get bare metal working outside of an emulator (#609)
You can now run bare metal on bare metal!

* Fix handling of int 0x15 eax = 0xe820 memory map
* Fix some issues in initial page table creation
* hello4.com now works outside emulators
* Ensure area for identity page tables are zeroed first
* Simplify logic for creating page table entries, this partly
  reverts 577c0f6226
* Add degenerate MBR partition entry, to ease testing

Co-authored-by: tkchia <[email protected]>
2022-09-13 02:01:49 -07:00
Justine Tunney 9cf2bdc9a8 Rebuild compile.com
This updates the bootstrap binary for the build compile command wrapper,
which was recently updated by #602.
2022-09-13 01:50:20 -07:00
Connor ed5b763a0c Refine V=0 command logging (#602)
This fixes off-by-one bugs, as well as missing carriage returns
caused by command truncation. When the terminal's width is 0 or
unknown, line feeds are used instead. Otherwise, the command is
padded with spaces to clear the line when the terminal is dumb.
2022-09-13 01:48:28 -07:00
Justine Tunney 22b63d0b98 Add *NSYNC to libc/isystem 2022-09-13 01:47:12 -07:00
Justine Tunney 6f7d0cb1c3 Pay off more technical debt
This makes breaking changes to add underscores to many non-standard
function names provided by the c library. MODE=tiny is now tinier and
we now use smaller locks that are better for tiny apps in this mode.
Some headers have been renamed to be in the same folder as the build
package, so it'll be easier to know which build dependency is needed.
Certain old misguided interfaces have been removed. Intel intrinsics
headers are now listed in libc/isystem (but not in the amalgamation)
to help further improve open source compatibility. Header complexity
has also been reduced. Lastly, more shell scripts are now available.
2022-09-12 23:36:56 -07:00
Justine Tunney b69f3d2488 Optimize memory layout 2022-09-12 04:26:52 -07:00
3702 changed files with 140464 additions and 51440 deletions

No files matched your search

+5 -2
View File
@@ -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 }}
+118 -92
View File
@@ -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
+31 -20
View File
@@ -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.
+663 -97
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
BIN
View File
Binary file not shown.
File renamed without changes.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33 -33
View File
@@ -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
View File
@@ -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
View File
@@ -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
+31
View File
@@ -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
View File
@@ -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"
+34
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) $<
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+9 -3
View File
@@ -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
View File
@@ -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);
}
}
+58
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+5 -8
View File
@@ -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");
}
+2 -2
View File
@@ -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());
}
+6 -4
View File
@@ -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}, //
+4 -4
View File
@@ -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
View File
@@ -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},
+55
View File
@@ -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
View File
@@ -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;
-160
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+43
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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;
}
+1
View File
@@ -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"
+127
View File
@@ -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;
}
}
}
+39
View File
@@ -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
View File
@@ -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"
+521
View File
@@ -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);
}
+100
View File
@@ -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
+39
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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"
/**
+42
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+60
View File
@@ -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);
}
}
}
+39
View File
@@ -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
View File
@@ -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;
}
+617
View File
@@ -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);
}
+21
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+41 -58
View File
@@ -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();
}
}
+25 -30
View File
@@ -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
+43
View File
@@ -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();
}
}
+93
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+6 -1
View File
@@ -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_ */
+22
View File
@@ -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_ */
+19
View File
@@ -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
View File
@@ -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