Compare commits

...
225 Commits
Author SHA1 Message Date
Justine Tunney af2ef0d223 Fix the build 2022-10-14 11:18:40 -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
Connor 0305194d98 Left-align stub arguments to dd (fixes #374) (#598)
This satisfies busybox's non-standard integer
argument parsing, and even saves a few bytes.
2022-09-12 04:26:38 -07:00
Paul Kulchenko 55ddf73484 Update redbean doc to correct return values (#610) 2022-09-11 19:51:18 -07:00
tkchia 569c031934 Don't pushpop in long mode without stack (#611) 2022-09-11 19:50:32 -07:00
Justine Tunney 9b89a7c51d Add *NSYNC mu_test 2022-09-11 18:56:29 -07:00
Justine Tunney b5cb71ab84 Use *NSYNC for POSIX threads locking APIs
Condition variables, barriers, and r/w locks now work very well.
2022-09-11 11:04:50 -07:00
Justine Tunney 3de35e196c Fix the build 2022-09-10 19:57:50 -07:00
Justine Tunney 5dff63a31c Import nsync 2022-09-10 16:12:31 -07:00
Justine Tunney cdb2284f0d Remove stdio lock macros from amalgamation 2022-09-10 12:03:36 -07:00
Justine Tunney 333768440c Clean up the TLS code 2022-09-10 11:49:13 -07:00
Justine Tunney cfcf5918bc Rewrite recursive mutex code 2022-09-10 09:18:52 -07:00
tkchia bae7367774 Bare metal VGA: minor improvements (#608) 2022-09-10 04:28:28 -07:00
Justine Tunney 155b378a39 Tidy up the threading implementation
The organization of the source files is now much more rational.
Old experiments that didn't work out are now deleted. Naming of
things like files is now more intuitive.
2022-09-10 02:56:25 -07:00
Justine Tunney e9272f03fb Make some minor touchups for nightlies 2022-09-09 19:12:40 -07:00
Justine Tunney 3265324e00 Don't relocate file descriptor memory
This change fixes #496 where ASAN spotted a race condition that could
happen in multithreaded programs, with more than OPEN_MAX descriptors
when using ZipOS or Windows NT, which require tracking open file info
and this change fixes that table so it never relocates, thus allowing
us to continue to enjoy the benefits of avoiding locks while reading.
2022-09-09 16:54:28 -07:00
Justine Tunney c3208eb9d5 Add more POSIX threads APIs 2022-09-09 11:30:33 -07:00
Justine Tunney 1729a8259c Introduce MODE=fastbuild for 28% speedup 2022-09-09 08:59:59 -07:00
Gautham 094ccbb4bd Add more foo64 stubs for Rust (#607) 2022-09-09 06:50:45 -07:00
Justine Tunney e97f1a99cf Fix pthread stacks with larger guard size 2022-09-09 06:41:22 -07:00
tkchiaandtkchia 1db76c288e Bare metal VGA: enable bright background colors, disable blinking (#603)
Co-authored-by: tkchia <[email protected]>
2022-09-09 04:35:16 -07:00
Paul Kulchenko f68151c010 Add sigpending to redbean unix.* module (#605) 2022-09-09 04:20:13 -07:00
Justine Tunney 2d17ab016c Perform more low-level code cleanup 2022-09-09 04:07:08 -07:00
Gautham c32e2d4486 Set stackaddr if mmap is called in pthread_create (#606) 2022-09-08 21:07:53 -07:00
Paul Kulchenko 5140897c27 Update redbean to include params in slash redirect (#604) 2022-09-08 19:14:54 -07:00
Justine Tunney 9f963dc597 Clean up some of the threading code 2022-09-08 12:31:56 -07:00
Justine Tunney 0547eabcd6 Polyfill IPv6 on non-Linux 2022-09-08 06:06:22 -07:00
Justine Tunney b73e35c6fa Improve open source compatibility
This change tunes the default stack size for the outside world to 8mb
while at the same time, reducing Cosmopolitan's default stack size to
64kb. You can override the stack size using STATIC_STACK_SIZE(). Your
build scripts should point to o//ape/public/ape.lds

This change also fixes the definition of SOMAXCONN and removes AF_RDS
since it's not polyfilled and Python 3.11 complained.
2022-09-08 03:19:35 -07:00
Justine Tunney 0e2b1bfeed Make garbage collection thread safe
- You can now use _gc(malloc()) in multithreaded programs
- This change fixes a bug where fork() on NT disabled TLS
- Fixed TLS code morphing on XNU/NT, for R8-R15 registers
2022-09-08 02:33:01 -07:00
Justine Tunney 571c2c3c69 Fix race condition in makedirs() 2022-09-07 23:12:44 -07:00
Gavin Hayes b7c07d548c Add FP_ILOGB constants (#599) 2022-09-07 21:37:53 -07:00
Justine Tunney 6c323383e5 Make some fixups to POSIX threads 2022-09-07 21:13:50 -07:00
Justine Tunney de511bc71a Add phtread_setname_np() and pthread_getname_np() 2022-09-07 19:04:05 -07:00
Justine Tunney 114176c304 Add more foo64() functions for Rust 2022-09-07 05:48:57 -07:00
Gavin Hayes a849a63771 Implement sigpending for sysv and nt (#597) 2022-09-07 05:38:12 -07:00
Justine Tunney 4339d9f15e Add pthread attributes and other libc functions 2022-09-07 05:28:32 -07:00
Justine Tunney d5c9308a43 Don't sandbox documentation generator 2022-09-06 20:45:21 -07:00
Justine Tunney 8bd9ad8342 Simplify redbean serialization code 2022-09-06 20:07:29 -07:00
tkchia 3fdb1c14f1 Add VGA support on bare metal (#588)
If your main module has this declaration:

    STATIC_YOINK("vga_console");

Then a VGA driver will be linked into your executable which
displays your stdio characters on the PC display, whereas
before we could only use the serial port. Your display is an
ANSI terminal and it's still a work in progress.
2022-09-06 18:41:08 -07:00
Gavin Hayes 598640864a Fix inability to add some signals to mask on NT (#596) 2022-09-06 18:35:26 -07:00
Justine Tunney d861d2787b Import OpenBSD sorting algorithms
OpenBSD's qsort() function is more secure than the ones used by
FreeBSD, NetBSD and MacOS. The best part is it goes faster too!
This change also imports the OpenBSD mergesort() and heapsort()
2022-09-06 17:52:26 -07:00
Justine Tunney dbf12c30b0 Make more compatibility improvements 2022-09-06 12:36:34 -07:00
Justine Tunney 11ec60d5fc Use a better sorting algorithm
This change changes qsort() to use the same code as NetBSD and MacOS
because it goes 6x faster than Musl's SmoothSort function. Smoothsort
can still be used if you need something that's provenly linearithmic.
This change also improves GNU Make performance on whole by 7 percent!

netbsd nearly   l:    70,196c    22,673ns   m:    68,428c    22,102ns
musl nearly     l:    53,844c    17,391ns   m:    58,726c    18,968ns
unixv6 nearly   l:    65,885c    21,280ns   m:    63,082c    20,375ns

netbsd reverse  l:   120,290c    38,853ns   m:   122,619c    39,605ns
musl reverse    l:   801,826c   258,985ns   m:   794,689c   256,680ns
unixv6 reverse  l:    58,977c    19,049ns   m:    59,764c    19,303ns

netbsd random   l:   146,745c    47,398ns   m:   145,782c    47,087ns
musl random     l:   855,804c   276,420ns   m:   850,912c   274,840ns
unixv6 random   l:   214,325c    69,226ns   m:   213,906c    69,090ns

netbsd 2n       l:    77,299c    24,967ns   m:    76,773c    24,797ns
musl 2n         l:   818,012c   264,213ns   m:   818,282c   264,301ns
unixv6 2n       l: 3,967,009c 1,281,322ns   m: 3,941,792c 1,273,177ns

https://justine.lol/dox/sort.pdf
2022-09-06 11:06:10 -07:00
Justine Tunney 55c6297e13 Make more compatibility improvements 2022-09-06 07:04:13 -07:00
Justine Tunney 12d9e1e128 Improve quality of our ANSI C clock() function
It now works most excellently across all supported operating
sytsems (earlier it didn't work on NT and XNU). Demo code is
available in examples/clock.c and this change also adds some
of the newer ANSI C time functions like timespec_get(), plus
timespec_getres() which hasn't even come out yet as it's C23
2022-09-05 23:03:49 -07:00
Justine Tunney 7ff0ea8c13 Make pthread mutexes more scalable
pthread_mutex_lock() now uses a better algorithm which goes much faster
in multithreaded environments that have lock contention. This comes at
the cost of adding some fixed-cost overhead to mutex invocations. That
doesn't matter for Cosmopolitan because our core libraries all encode
locking operations as NOP instructions when in single-threaded mode.
Overhead only applies starting the moment you first call clone().
2022-09-05 15:57:51 -07:00
Gavin Hayes 7de2f229a7 Discard ignored signals on New Technology (#592) 2022-09-05 09:17:56 -07:00
Gautham 4b4ea046c4 Ensure libcxx.a is built when providing folder (#591) 2022-09-05 09:17:16 -07:00
Justine Tunney 44c315d789 Disable pthread broadcast test temporarily
This fixes the GitHub Actions build.
2022-09-05 09:06:16 -07:00
Justine Tunney 8cd4248f7f Make SIG_DFL / SIG_IGN C++ compatible 2022-09-05 08:49:26 -07:00
Justine Tunney d721ff8938 Remove testonly keyword 2022-09-05 08:41:43 -07:00
Justine Tunney 9be364d40a Implement POSIX threads API 2022-09-05 08:27:15 -07:00
Justine Tunney af24f21556 Unsandbox assembly generation 2022-09-05 08:27:15 -07:00
Paul Kulchenko b0287ef34c Tune a log message priority in redbean (#589) 2022-09-04 07:43:06 -07:00
Justine Tunney 6a04bc3318 Release redbean 2.0.18 2022-09-04 06:57:59 -07:00
Justine Tunney 8dd4ec68d0 Add more missing C / C++ headers 2022-09-04 04:53:52 -07:00
Justine Tunney b9dc74b672 Do some work on unbuffer command 2022-09-04 02:25:34 -07:00
Justine Tunney e1590e1e38 Remove accidental comment 2022-09-04 00:41:09 -07:00
tkchiaandtkchia 8569704c1d Stop APE bare metal loader from reading beyond program image end (#574)
This allows e.g. `qemu-system-x86_64 -s o/examples/hello.com
-serial stdio` to work without having to add extra padding to
the end of the `hello.com` "disk image".

(The sector count computation is divided among two instructions
in the assembly code.  This is done on purpose, to prevent an
ASCII 0x27 (single quote) byte from appearing in the bare
metal loader code, which will break the shell script loader.
There is probably a better way.)

Co-authored-by: tkchia <[email protected]>
2022-09-04 00:19:08 -07:00
Gavin Hayes 9c017c98d3 Add sysconf to unistd.h (#575) 2022-09-04 00:10:17 -07:00
Gavin Hayes 74879bf067 Add pollfd to poll.h (#576) 2022-09-04 00:09:50 -07:00
Paul Kulchenko 8a3d8497e3 Update README to add a note about binfmt-related errors (#587) 2022-09-04 00:09:24 -07:00
Justine Tunney 3c00d8c29c Fix TLS linker warning
Fixes #565
Closes #577
Co-authored-by: tkchia <[email protected]>
2022-09-04 00:05:30 -07:00
Gavin Hayes 1ef955c33b Improve zipos path handling (#579)
This change adds opendir, readdir, and stat support for the /zip/ root,
as well as directories not explicitly encoded in the zip file.
2022-09-03 22:50:23 -07:00
Gavin Hayes 494d74271b Fix inet_ntop(AF_INET6) buffer length (#582) 2022-09-03 22:46:45 -07:00
Ilya Brin 12212894eb Highlight GDB syntax in README.md (#560) 2022-09-03 22:19:55 -07:00
Justine Tunney a4522fba8d Fix build 2022-09-03 21:10:37 -07:00
Justine Tunney 0c70e8963d Add notpossible keyword
This is the same as `unreachable` except it always traps violations,
even if we're not running in MODE=dbg. This is useful for impossible
conditions relating to system calls. It avoids terrifying bugs where
control falls through to an unrelated function.
2022-09-03 20:35:31 -07:00
Justine Tunney b66bd064d8 Improve quality of uname/gethostname/getdomainname 2022-09-03 20:20:40 -07:00
Justine Tunney c5c4dfcd21 Improve quality of raise(), abort(), and tkill()
This change fixes a nasty bug where SIG_IGN and SIG_DFL weren't working
as advertised on BSDs. This change also fixes the tkill() definition on
MacOS so it maps to __pthread_kill().
2022-09-03 20:17:54 -07:00
Justine Tunney c5659b93f8 Create unit test framework for subprocesses 2022-09-03 18:02:01 -07:00
Gavin Hayes 263711965f Change sigaction_f to match sysv signature (#585) 2022-09-02 05:08:35 -07:00
Paul Kulchenko 33b5b5b312 Remove path escaping from LaunchBrowser (#584)
This is so you can have `?query=args`.
2022-08-31 22:14:06 -07:00
Gavin Hayes d213a48190 Implement inet_pton for AF_INET6 (#583) 2022-08-31 15:14:42 -07:00
Paul Kulchenko 3f0414e1cb Fix JSON single quote escaping (fixes #512) 2022-08-31 07:53:57 -05:00
Gavin Hayes adaaeb7dd0 Add itimerval to sys/time.h (#572) 2022-08-26 09:44:41 -07:00
Paul Kulchenko 164e2ab27b Rename MapContentType to ProgramContentType (#570) 2022-08-24 09:35:17 -07:00
Paul Kulchenko d2cec808dc Fix redbean to check for file read result when -F option is used (#569) 2022-08-23 20:54:51 -07:00
Paul Kulchenko 91a3252434 Add MapContentType to redbean (#566) 2022-08-22 22:02:58 -07:00
Justine Tunney 8cab92a069 Release awk-2022-08-22.com 2022-08-22 21:28:19 -07:00
Justine Tunney 5a632cf72d Add lchown, lchmod, statvfs, fstatvfs 2022-08-22 20:50:16 -07:00
Gautham 7b74f6e20e Tidy up pydoc help (#567) 2022-08-22 20:40:00 -07:00
Justine Tunney 253cc1754b Shave another 2% off GNU Make latency 2022-08-22 17:42:32 -07:00
Justine Tunney 8722006c46 Shave another 10% off GNU Make latency
We avoid memcpy() by creating a likely branch with a constant size.
2022-08-22 17:04:54 -07:00
Justine Tunney 58d22c7c3d Handle missing stdio handles on Windows 2022-08-22 17:03:11 -07:00
Justine Tunney 2227cefa5d Run fix-third-party.py and man2txt on sed 2022-08-21 22:26:48 -07:00
Justine Tunney f0bf9f3389 Import NetBSD sed 2022-08-21 22:26:48 -07:00
Paul Kulchenko 04cd62c319 Update redbean GetResponseBody to take response compression into account (#561) 2022-08-21 22:26:41 -07:00
Paul Kulchenko e204fc0820 Update redbean If-Modified-Since check to accept same timestamp (#562) 2022-08-21 22:03:30 -07:00
Justine Tunney b76540105d Release Cosmopolitan v2.0.1 2022-08-21 18:59:20 -07:00
Justine Tunney 14e3025749 Release redbean 2.0.17 2022-08-21 18:35:53 -07:00
Justine Tunney 51fa5535ac Fix regression in Fetch() 2022-08-21 18:32:57 -07:00
Justine Tunney bea0b55576 Fix If-Modified-Since regression 2022-08-21 18:05:05 -07:00
Justine Tunney 57b39d8793 Revert recent fixupobj.com change 2022-08-21 17:33:54 -07:00
Justine Tunney d52170ca34 Avoid zip -d redbean.com foo issue on Windows 2022-08-21 16:32:57 -07:00
Justine Tunney bf757c4646 Fix _Thread_local with fork() on Windows 2022-08-21 15:51:44 -07:00
Justine Tunney 99a92048b4 Get awk to build and make it hackable 2022-08-21 13:39:20 -07:00
Justine Tunney 2f1679e5cf Import The One True Awk
https://github.com/onetrueawk/awk
2022-08-21 13:38:12 -07:00
Justine Tunney ee49b71be2 Fix build 2022-08-21 01:11:14 -07:00
Justine Tunney 73845be1f0 Restore zip.com and .symtab files
This change restores the .symtab symbol table files in our flagship
programs (e.g. redbean.com, python.com) needed to show backtraces. This
also rolls back earlier changes to zip.com w.r.t. temp directories since
the right way to do it turned out to be the -b DIR flag.

This change also improves the performance of zip.com. It turned out
mmap() wasn't being used, because zip.com was assuming a 4096-byte
granularity, but cosmo requires 65536. There was also a chance to speed
up stdio scanning using the unlocked functions.
2022-08-21 00:17:20 -07:00
Justine Tunney 35203c0551 Do some string library work 2022-08-20 22:17:14 -07:00
Justine Tunney 83d41e4588 Clean up some code 2022-08-20 12:32:51 -07:00
Paul Kulchenko a51edaa0db Remove .heartbeat.lua from redbean (#554)
It's been replaced by `OnServerHeartbeat`.
2022-08-20 01:31:58 -07:00
Justine Tunney d76dfadc7a Reduce GNU Make latency 17% for cosmo
fgets() is now 4x faster which makes Make 2% faster. Landlock Make now
has a builtin $(uniq ...) function that uses critbit trees rather than
functional programming. Since uniq is the most important function this
optimization makes our cold start latency 15% faster.
2022-08-19 15:29:24 -07:00
Justine Tunney 8835b82a7c Avoid sandboxing directory prerequisites
Landlock Make will no longer sandbox prerequisites that end with a
trailing slash. This means you can use use directory prerequisites
for detecting deleted files when using using globbing, without the
effect of unveiling the entire directory. When you do want make to
unveil directories, you can omit the trailing slash.
2022-08-19 13:02:25 -07:00
Daniil Kulchenko 2827df688a Fix M1 Rosetta signal handling (#455) (#553)
Rosetta does something strange to the signal handling registers but
setting SA_SIGINFO prevents the issue from happening. Set the flag
on XNU to work around the issue.
2022-08-19 13:00:50 -07:00
3332 changed files with 120828 additions and 31973 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 }}
+2
View File
@@ -11,3 +11,5 @@ __pycache__
/TAGS
/bx_enh_dbg.ini
/tool/emacs/*.elc
/perf.data
/perf.data.old
+2 -2
View File
@@ -43,10 +43,10 @@
"forcealignargpointer=",
"noasan=",
"noubsan=",
"testonly=",
"donothing=",
"nosideeffect=",
"unreachable=",
"unreachable=",,
"notpossible=",
"thatispacked=",
"dontthrow=",
"nocallback=",
+114 -79
View File
@@ -61,13 +61,19 @@
SHELL = build/bootstrap/cocmd.com
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += -j --no-builtin-rules
.SUFFIXES:
.DELETE_ON_ERROR:
.FEATURES: output-sync
.PHONY: all o bins check test depend tags
ifneq ($(m),)
ifeq ($(MODE),)
MODE := $(m)
endif
endif
all: o
o: o/$(MODE)
@@ -88,11 +94,13 @@ o/$(MODE): \
libc/disclaimer.inc \
rx:build/bootstrap \
rx:o/third_party/gcc \
/proc/self/status \
/proc/stat \
rw:/dev/null \
w:o/stack.log \
/etc/hosts \
~/.runit.psk
~/.runit.psk \
/proc/self/status \
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
PKGS =
@@ -113,17 +121,21 @@ 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/fmt/fmt.mk # │
include libc/vga/vga.mk #─┘
include libc/calls/calls.mk #─┐
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
include libc/crt/crt.mk # │ You can issue system calls
include third_party/nsync/nsync.mk # │
include third_party/dlmalloc/dlmalloc.mk #─┘
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 # │
@@ -149,6 +161,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
@@ -156,8 +169,10 @@ 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/sed/sed.mk
include third_party/awk/awk.mk
include third_party/make/make.mk
include third_party/finger/finger.mk
include third_party/argon2/argon2.mk
@@ -189,6 +204,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
@@ -206,6 +222,7 @@ include test/libc/fmt/test.mk
include test/libc/dns/test.mk
include test/libc/time/test.mk
include test/libc/stdio/test.mk
include test/libc/zipos/test.mk
include test/libc/release/test.mk
include test/libc/test.mk
include test/net/http/test.mk
@@ -258,94 +275,102 @@ 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: private .UNSANDBOXED = 1
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
@$(RM) $@
@$(TAGS) $(TAGSFLAGS) -L $< -o $@
HTAGS: .UNSANDBOXED = 1
HTAGS: private .UNSANDBOXED = 1
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
@$(RM) $@
@build/htags -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 \
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 \
# 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_XED \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_X \
LIBC_ZIPOS \
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_ZLIB \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_REGEX
o/$(MODE)/cosmopolitan.a: \
@@ -359,6 +384,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: private .UNSANDBOXED = 1
o/cosmopolitan.html: \
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
@@ -377,6 +403,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
+36 -18
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.zip
unzip cosmopolitan-amalgamation-2.0.zip
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.1.1.zip
unzip cosmopolitan-amalgamation-2.1.1.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
@@ -40,6 +40,21 @@ You now have a portable program.
bash -c './hello.com' # zsh/fish workaround (we patched them in 2021)
```
If `./hello.com` executed on Linux throws an error about not finding an
interpreter, it should be fixed by running the following command (although
note that it may not survive a system restart):
```sh
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
```
If the same command produces puzzling errors on WSL or WINE when using
Redbean 2.x, they may be fixed by disabling binfmt_misc:
```sh
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:-.}}`
@@ -85,7 +100,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
@@ -140,7 +155,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
```
@@ -159,7 +174,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
@@ -168,7 +183,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
```
@@ -176,18 +191,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).
@@ -196,7 +212,7 @@ For further details, see [//build/config.mk](build/config.mk).
Here's the recommended `~/.gdbinit` config:
```
```gdb
set host-charset UTF-8
set target-charset UTF-8
set target-wide-charset UTF-8
@@ -229,11 +245,11 @@ 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 | 2012 |
| Mac OS X | 15.6 | 2018 |
| FreeBSD | 13 | 2020 |
| OpenBSD | 6.4 | 2018 |
| FreeBSD | 13 | 2020 |
| NetBSD | 9.2 | 2021 |
## Special Thanks
@@ -242,8 +258,10 @@ 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.
+83 -53
View File
@@ -39,7 +39,6 @@
#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"
@@ -126,6 +125,7 @@ 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
@@ -236,8 +236,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
@@ -328,7 +329,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
@@ -381,11 +382,11 @@ pcread: push %ax
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
@@ -484,19 +485,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
@@ -548,7 +549,7 @@ 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
// 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.
@@ -568,11 +569,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape\"\n"
.ascii "[ -x \"$t\" ] || {\n"
.ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=\""
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
.shstub ape_loader_dd_skip,2
.ascii "\" count=\""
.ascii " count="
.shstub ape_loader_dd_count,2
.ascii "\" bs=64 2>/dev/null\n"
.ascii " bs=64 2>/dev/null\n"
#if SupportsXnu()
.ascii "[ -d /Applications ] && "
.ascii "dd if=\"$t.$$\""
@@ -636,11 +637,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "dd if=\"$o\""
.ascii " of=\"$o\""
.ascii " bs=8"
.ascii " skip=\""
.ascii " skip="
.shstub ape_macho_dd_skip,2
.ascii "\" count=\""
.ascii " count="
.shstub ape_macho_dd_count,2
.ascii "\" conv=notrunc 2>/dev/null\n"
.ascii " conv=notrunc 2>/dev/null\n"
#endif /* XNU */
.ascii "[ x\"$1\" = x--assimilate ] && exit 0\n"
#ifndef APE_NO_MODIFY_SELF
@@ -873,7 +874,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
@@ -1136,12 +1137,17 @@ 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
_gdtrphy:
.short 2f-1f-1 # table byte length
.long REAL(1f) # table address (physical space)
.endobj _gdtrphy,global,hidden
_gdtr:
.short 2f-1f-1 # table byte length
.quad 1f # table address (final virtual space)
.endobj _gdtr,global,hidden
.align 8
_gdt:
1:
// ┌G:granularity (1 → limit *= 0x1000)
// │┌D/B:default operation size (0 = 16|64bit, 1 = 32-bit)
@@ -1171,7 +1177,9 @@ gdt: .short 2f-1f # table byte length
.quad 0b0000000011001111100100100000000000000000000000001111111111111111 #32
.quad 0b0000000010101111100110110000000000000000000000001111111111111111 #40
.quad 0b0000000010101111100100110000000000000000000000001111111111111111 #48
2: .endobj gdt,global,hidden
.tssdescstub _tss #56,64
2:
.endobj _gdt,global,hidden
/*─────────────────────────────────────────────────────────────────────────────╗
│ αcτµαlly pδrταblε εxεcµταblε § real mode │
@@ -1277,8 +1285,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
@@ -1288,29 +1296,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
@@ -1380,9 +1398,16 @@ a20: cli
// Initializes long mode paging.
pinit: push %ds
push %es
#define SEG 0x79000
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 (+)
@@ -1390,14 +1415,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
@@ -1406,15 +1432,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(_gdtrphy)
mov %cr0,%eax
or $CR0_PE|CR0_PG|CR0_MP,%eax
and $~CR0_EM,%eax
@@ -1424,14 +1450,16 @@ golong: cli
// Long mode is long.
.code64
long: push $GDT_LONG_DATA
pop %rax
long: xor %eax,%eax
mov $GDT_LONG_DATA,%al
mov %eax,%ds
mov %eax,%ss
mov %eax,%es
mov %eax,%fs
mov %eax,%gs
mov $0x80000,%esp
mov $GDT_LONG_TSS,%al
ltr %ax
xor %r12d,%r12d
xor %r13d,%r13d
xor %r14d,%r14d
@@ -1439,12 +1467,14 @@ long: push $GDT_LONG_DATA
xor %ebx,%ebx
xor %ebp,%ebp
push %rbp
mov $0x0500,%rdi # mman
mov $mm,%rdi
mov %cr3,%rsi
mov $IMAGE_BASE_REAL,%edx
call __map_phdrs
push $0x037f
fldcw (%rsp)
lgdt _gdtr # reload GDTR for
# virtual memory space
movabs $kernel,%rax
jmp *%rax
.endfn long
@@ -1525,7 +1555,7 @@ 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
push $_HOSTMETAL # sets __hostos in crt.S
pop %rcx
push $0
mov %rsp,%rbp
+18 -9
View File
@@ -180,6 +180,7 @@
#include "libc/elf/def.h"
#include "libc/elf/pf2prot.internal.h"
#include "libc/nt/pedef.internal.h"
#include "libc/thread/tls.h"
#include "libc/zip.h"
ENTRY(_start)
@@ -279,6 +280,7 @@ SECTIONS {
KEEP(*(.keep.text))
*(.text .stub .text.*)
KEEP(*(SORT_BY_NAME(.sort.text.*)))
*(.subrs)
KEEP(*(.ape.pad.test));
*(.test.unlikely)
@@ -380,17 +382,16 @@ SECTIONS {
PROVIDE_HIDDEN(edata = .);
KEEP(*(SORT_BY_NAME(.zip.*)))
HIDDEN(_ezip = .);
. = ALIGN(PAGESIZE);
} :Ram
.tdata . : {
_tdata_start = .;
*(SORT_BY_ALIGNMENT(.tdata))
*(SORT_BY_ALIGNMENT(.tdata.*))
. = ALIGN(16);
_tdata_end = .;
. = ALIGN(PAGESIZE);
} :Tls
. = ALIGN(PAGESIZE);
} :Tls :Ram
/*END: file content that's loaded by o/s */
/*BEGIN: bss memory void */
@@ -399,7 +400,7 @@ SECTIONS {
_tbss_start = .;
*(SORT_BY_ALIGNMENT(.tbss))
*(SORT_BY_ALIGNMENT(.tbss.*))
. = ALIGN(16);
. = ALIGN(TLS_ALIGNMENT);
/* the %fs register is based on this location */
_tbss_end = .;
} :Tls
@@ -426,7 +427,7 @@ SECTIONS {
KEEP(*(.bssepilogue))
/*END: NT FORK COPYING */
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
. = ALIGN(PAGESIZE);
HIDDEN(_end = .);
PROVIDE_HIDDEN(end = .);
} :Bss
@@ -457,6 +458,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) }
@@ -465,6 +467,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)) }
@@ -485,8 +488,10 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
PFSTUB4(ape_elf_shnum, 0);
PFSTUB4(ape_elf_shstrndx, 0);
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
HIDDEN(_tls_size = _tbss_end - _tdata_start);
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
HIDDEN(_tbss_size = _tbss_end - _tbss_start);
HIDDEN(_tbss_offset = _tbss_start - _tdata_start);
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
@@ -560,10 +565,11 @@ SHSTUB2(ape_loader_dd_count,
#if SupportsMetal()
HIDDEN(v_ape_realsectors =
MIN(0x70000 - IMAGE_BASE_REAL,
ROUNDUP(RVA(_edata), 4096)) / 512);
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);
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
#endif
/* ZIP End of Central Directory header */
@@ -708,8 +714,11 @@ 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");
/* Let's not be like Knight Capital. */
/* NOCROSSREFS_TO(.test .text) */
+21
View File
@@ -63,7 +63,27 @@ o/$(MODE)/ape/ape.lds: \
ape/macros.internal.h \
ape/relocations.h \
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 \
libc/macros.internal.h \
libc/nt/pedef.internal.h \
libc/str/str.h \
libc/zip.h
o/$(MODE)/ape/public/ape.lds: OVERRIDE_CPPFLAGS += -UCOSMO
o/$(MODE)/ape/public/ape.lds: \
ape/public/ape.lds \
ape/ape.lds \
ape/macros.internal.h \
ape/relocations.h \
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 \
@@ -159,6 +179,7 @@ o/$(MODE)/ape/ape.macho.dbg: \
o/$(MODE)/ape: $(APE_CHECKS) \
o/$(MODE)/ape/ape.o \
o/$(MODE)/ape/ape.lds \
o/$(MODE)/ape/public/ape.lds \
o/$(MODE)/ape/ape.elf \
o/$(MODE)/ape/ape.macho \
o/$(MODE)/ape/ape-copy-self.o \
+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
+17 -17
View File
@@ -179,7 +179,7 @@ struct ElfPhdr {
extern char ehdr[];
extern char _end[];
static void *syscall;
static void *syscall_;
static char relocated;
static struct PathSearcher ps;
extern char __syscall_loader[];
@@ -275,7 +275,7 @@ __attribute__((__noreturn__)) static void Exit(int rc, int os) {
asm volatile("call\t*%2"
: /* no outputs */
: "a"((IsLinux() ? 60 : 1) | (IsXnu() ? 0x2000000 : 0)), "D"(rc),
"rm"(syscall)
"rm"(syscall_)
: "memory");
__builtin_unreachable();
}
@@ -285,7 +285,7 @@ static void Close(int fd, int os) {
asm volatile("call\t*%4"
: "=a"(ax), "=D"(di)
: "0"((IsLinux() ? 3 : 6) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"rm"(syscall)
"rm"(syscall_)
: "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc");
}
@@ -295,7 +295,7 @@ static int Read(int fd, void *data, int size, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 0 : 3) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"2"(data), "3"(size), "rm"(syscall)
"2"(data), "3"(size), "rm"(syscall_)
: "rcx", "r8", "r9", "r10", "r11", "memory");
return ax;
}
@@ -306,7 +306,7 @@ static void Write(int fd, const void *data, int size, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 1 : 4) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
"2"(data), "3"(size), "rm"(syscall)
"2"(data), "3"(size), "rm"(syscall_)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}
@@ -315,7 +315,7 @@ static void Execve(const char *prog, char **argv, char **envp, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"(59 | (IsXnu() ? 0x2000000 : 0)), "1"(prog), "2"(argv),
"3"(envp), "rm"(syscall)
"3"(envp), "rm"(syscall_)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
}
@@ -325,7 +325,7 @@ static int Access(const char *path, int mode, int os) {
asm volatile("call\t*%7"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 21 : 33) | (IsXnu() ? 0x2000000 : 0)),
"1"(path), "2"(mode), "rm"(syscall)
"1"(path), "2"(mode), "rm"(syscall_)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@@ -338,7 +338,7 @@ static int Msyscall(long p, long n, int os) {
} else {
asm volatile("call\t*%6"
: "=a"(ax), "=D"(di), "=S"(si)
: "0"(37), "1"(p), "2"(n), "rm"(syscall)
: "0"(37), "1"(p), "2"(n), "rm"(syscall_)
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@@ -350,7 +350,7 @@ static int Open(const char *path, int flags, int mode, int os) {
asm volatile("call\t*%8"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"((IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0)),
"1"(path), "2"(flags), "3"(mode), "rm"(syscall)
"1"(path), "2"(flags), "3"(mode), "rm"(syscall_)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
@@ -369,7 +369,7 @@ __attribute__((__noinline__)) static long Mmap(long addr, long size, int prot,
"pop\t%%r9"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx), "+r"(flags_),
"+r"(fd_), "+r"(off_)
: "rm"(syscall),
: "rm"(syscall_),
"0"((IsLinux() ? 9
: IsFreebsd() ? 477
: 197) |
@@ -379,7 +379,7 @@ __attribute__((__noinline__)) static long Mmap(long addr, long size, int prot,
return ax;
}
static int MunmapLinux(const void *addr, unsigned long size) {
int MunmapLinux(const void *addr, unsigned long size) {
int ax;
asm volatile("syscall"
: "=a"(ax)
@@ -388,7 +388,7 @@ static int MunmapLinux(const void *addr, unsigned long size) {
return ax;
}
static int PrctlLinux(int op, long a, long b, long c, long d) {
int PrctlLinux(int op, long a, long b, long c, long d) {
int rc;
asm volatile("mov\t%5,%%r10\n\t"
"mov\t%6,%%r8\n\t"
@@ -589,7 +589,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
// since it probably means a userspace program executed this loader
// and passed us a custom syscall function earlier.
if (Msyscall(code, codesize, os) != -1) {
syscall = 0;
syscall_ = 0;
}
#if TROUBLESHOOT
@@ -600,7 +600,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
// to extend the behavior of this loader in the future. we don't need
// to clear the xmm registers since the ape loader should be compiled
// with the -mgeneral-regs-only flag.
register void *r8 asm("r8") = syscall;
register void *r8 asm("r8") = syscall_;
asm volatile("xor\t%%eax,%%eax\n\t"
"xor\t%%r9d,%%r9d\n\t"
"xor\t%%r10d,%%r10d\n\t"
@@ -659,10 +659,10 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
}
// get syscall function pointer
if (handoff && handoff->syscall) {
syscall = handoff->syscall;
if (handoff && handoff->systemcall) {
syscall_ = handoff->systemcall;
} else {
syscall = __syscall_loader;
syscall_ = __syscall_loader;
}
if (handoff) {
+1 -1
View File
@@ -14,7 +14,7 @@ struct ApeLoader {
int os;
char *prog;
char *page;
void *syscall;
void *systemcall;
};
#endif /* COSMOPOLITAN_APE_LOADER_H_ */
+65 -37
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__)
@@ -221,44 +235,58 @@
/**
* Binary coded decimal support.
*
* <p>This allows linker scripts to generate dd commands. Leading spaces
* need to be inserted so Mac doesn't consider them octal; therefore,
* parameters must be quoted; and eight digits should be good enough.
* <p>This allows linker scripts to generate dd commands, e.g. ape.lds.
* There are a few ways to pad each number to the necessary 8 bytes.
* Spaces cannot be prepended because busybox refuses to parse them.
* Zeros cannot be prepended because Mac will take numbers as octal.
* That leaves appending spaces. The user's shell ought to treat any
* unquoted run of spaces as if there was only one, so this is safe.
*/
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD10K(X)); \
HIDDEN(SYM##_bcs1 = BCD(X))
#define BCD(X) \
((X) == 0 \
? 0x20202030 \
: (X) < 10 ? 0x30202020 + (((X) % 10) << 24) \
: (X) < 100 ? 0x30302020 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) \
: (X) < 1000 ? 0x30303020 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) + \
(((X) / 100 % 10) << 8) \
: 0x30303030 + (((X) % 10) << 24) + \
(((X) / 10 % 10) << 16) + \
(((X) / 100 % 10) << 8) + \
(((X) / 1000 % 10) << 0))
#define BCD10K(X) \
((X) < 10000 \
? 0x20202020 \
: (X) < 100000 \
? 0x30202020 + (((X) / 10000 % 10) << 24) \
: (X) < 1000000 \
? 0x30302020 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) \
: (X) < 10000000 \
? 0x30303020 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) + \
(((X) / 1000000 % 10) << 8) \
: (X) < 100000000 \
? 0x30303030 + (((X) / 10000 % 10) << 24) + \
(((X) / 100000 % 10) << 16) + \
(((X) / 1000000 % 10) << 8) + \
(((X) / 10000000 % 10) << 0) \
: 0xffffffffffffffff)
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
#define BCD_SMEAR(X) ((X) + (X) * 10000)
#define BCD_LEFT(X) \
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
: (X) < 1000000 ? BCD_RIGHT(BCD_SMEAR((X) / 100)) \
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
: 0xffffffffffffffff)
#define BCD_RIGHT(X) \
(((X)) < 10000 ? 0x20202020 \
: (X) < 100000 ? 0x20202030 + \
(X) % 10 \
: (X) < 1000000 ? 0x20203030 + \
((X) / 10) % 10 + \
(X) % 10 * 0x100 \
: (X) < 10000000 ? 0x20303030 + \
((X) / 100) % 10 + \
((X) / 10) % 10 * 0x100 + \
(X) % 10 * 0x10000 \
: (X) < 100000000 ? 0x30303030 + \
((X) / 1000) % 10 + \
((X) / 100) % 10 * 0x100 + \
((X) / 10) % 10 * 0x10000 + \
(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_ */
+1
View File
@@ -0,0 +1 @@
#include "ape/ape.lds"
+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"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+95 -63
View File
@@ -4,20 +4,35 @@
# Default Mode
#
# - `make`
# - Optimized
# - Backtraces
# - Debuggable
# - Syscall tracing
# - Function tracing
# - Reasonably small
# - Reasonably optimized
# - Reasonably debuggable
#
ifeq ($(MODE),)
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-DSYSDEBUG \
-O2
TARGET_ARCH ?= \
-msse3
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
# Fast Build Mode
#
# - `make MODE=fastbuild`
# - No debugging
# - Syscall tracing
# - Function tracing
# - Some optimizations
# - Limited Backtraces
# - Compiles 28% faster
#
ifeq ($(MODE),fastbuild)
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O
CONFIG_CPPFLAGS += -DSYSDEBUG
CONFIG_OFLAGS += -g0
CONFIG_LDFLAGS += -S
TARGET_ARCH ?= -msse3
endif
# Optimized Mode
@@ -31,19 +46,11 @@ endif
# - No memory corruption detection
# - assert() / CHECK_xx() may leak code into binary for debuggability
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
#
ifeq ($(MODE), opt)
CONFIG_CPPFLAGS += \
-DNDEBUG \
-msse2avx \
-Wa,-msse2avx
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-DSYSDEBUG \
-O3 \
-fmerge-all-constants
TARGET_ARCH ?= \
-march=native
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -msse2avx -Wa,-msse2avx
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O3 -fmerge-all-constants
TARGET_ARCH ?= -march=native
endif
# Optimized Linux Mode
@@ -54,18 +61,12 @@ endif
# - Turns off function tracing
# - Turns off support for older cpu models
# - Turns off support for other operating systems
#
ifeq ($(MODE), optlinux)
CONFIG_CPPFLAGS += \
-DNDEBUG \
-msse2avx \
-Wa,-msse2avx \
-DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += \
-O3 -fmerge-all-constants
DEFAULT_COPTS += \
-mred-zone
TARGET_ARCH ?= \
-march=native
CONFIG_CPPFLAGS += -DNDEBUG -msse2avx -Wa,-msse2avx -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
DEFAULT_COPTS += -mred-zone
TARGET_ARCH ?= -march=native
endif
# Release Mode
@@ -81,16 +82,12 @@ endif
# - DCHECK_xx() statements removed
# - No memory corruption detection
# - CHECK_xx() won't leak strings into binary
#
ifeq ($(MODE), rel)
CONFIG_CPPFLAGS += \
-DNDEBUG
CONFIG_CCFLAGS += \
$(BACKTRACES) \
-O2
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
-O1
CONFIG_CPPFLAGS += -DNDEBUG
CONFIG_CCFLAGS += $(BACKTRACES) -O2
TARGET_ARCH ?= -msse3
PYFLAGS += -O1
endif
# Asan Mode
@@ -103,14 +100,11 @@ endif
# - Backtraces
# - Debuggability
# - Larger binaries
#
ifeq ($(MODE), asan)
CONFIG_CCFLAGS += \
$(BACKTRACES) \
-O2
CONFIG_COPTS += \
-fsanitize=address
TARGET_ARCH ?= \
-msse3
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
CONFIG_COPTS += -fsanitize=address
TARGET_ARCH ?= -msse3
endif
# Debug Mode
@@ -122,22 +116,13 @@ endif
# - Stack canaries
# - No optimization (TODO)
# - Enormous binaries
#
ifeq ($(MODE), dbg)
CONFIG_CPPFLAGS += \
-DMODE_DBG
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-DSYSDEBUG \
-O2 \
-fno-inline
CONFIG_COPTS += \
-fsanitize=address \
-fsanitize=undefined
TARGET_ARCH ?= \
-msse3
OVERRIDE_CCFLAGS += \
-fno-pie
CONFIG_CPPFLAGS += -DMODE_DBG
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O -fno-inline
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
TARGET_ARCH ?= -msse3
OVERRIDE_CCFLAGS += -fno-pie
endif
# Tiny Mode
@@ -151,6 +136,7 @@ endif
# - No backtraces
# - No algorithmics
# - YOLO
#
ifeq ($(MODE), tiny)
CONFIG_CPPFLAGS += \
-DTINY \
@@ -166,6 +152,10 @@ CONFIG_CCFLAGS += \
-fomit-frame-pointer \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
@@ -185,6 +175,7 @@ endif
# - No portability
# - No algorithmics
# - YOLO
#
ifeq ($(MODE), tinylinux)
CONFIG_CPPFLAGS += \
-DTINY \
@@ -193,6 +184,10 @@ CONFIG_CPPFLAGS += \
-DSUPPORT_VECTOR=1
DEFAULT_COPTS += \
-mred-zone
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
CONFIG_CCFLAGS += \
-Os \
-fno-align-functions \
@@ -216,6 +211,7 @@ endif
# - No backtraces
# - No algorithmics
# - YOLO
#
ifeq ($(MODE), tinylinuxbsd)
CONFIG_CPPFLAGS += \
-DTINY \
@@ -224,6 +220,10 @@ CONFIG_CPPFLAGS += \
-DSUPPORT_VECTOR=113
DEFAULT_COPTS += \
-mred-zone
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
CONFIG_CCFLAGS += \
-Os \
-fno-align-functions \
@@ -246,6 +246,7 @@ endif
# - No backtraces
# - No algorithmics
# - YOLO
#
ifeq ($(MODE), tinysysv)
CONFIG_CPPFLAGS += \
-DTINY \
@@ -260,6 +261,10 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
-S
TARGET_ARCH ?= \
-msse3
endif
@@ -276,6 +281,7 @@ endif
# - No backtraces
# - No algorithmics
# - YOLO
#
ifeq ($(MODE), tinynowin)
CONFIG_CPPFLAGS += \
-DTINY \
@@ -288,10 +294,36 @@ CONFIG_CCFLAGS += \
-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
+22 -24
View File
@@ -65,7 +65,6 @@ ZIPOBJ = build/bootstrap/zipobj.com
FIXUPOBJ = build/bootstrap/fixupobj.com
MKDIR = build/bootstrap/mkdir.com -p
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
SYMTAB = $(TMPDIR)/$(subst /,_,$@).symtab
COMMA := ,
PWD := $(shell build/bootstrap/pwd.com)
@@ -74,33 +73,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
@@ -108,6 +99,12 @@ export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
ifeq ($(LANDLOCKMAKE_VERSION),)
TMPSAFE = $(TMPDIR)/$(subst /,_,$@).tmp
else
TMPSAFE = $(TMPDIR)/
endif
FTRACE = \
-pg
@@ -143,6 +140,7 @@ DEFAULT_CCFLAGS = \
DEFAULT_OFLAGS = \
-g \
-gdwarf-4 \
-gdescribe-dies
DEFAULT_COPTS = \
+5 -1
View File
@@ -12,5 +12,9 @@
tail = $(wordlist 2,$(words $1),$1)
reverse = $(if $1,$(call reverse,$(call tail,$1)) $(firstword $1))
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1))
# polyfill uniq native (landlock make 1.4)
ifneq ($(call uniq,c b c a),c b a)
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
endif
+119 -19
View File
@@ -25,7 +25,6 @@ o/%.o: o/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/%.zip.o: o/% ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
@@ -44,14 +43,6 @@ o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.in
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-gcc.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
o/$(MODE)/%-clang.asm: CC = $(CLANG)
o/%.o: %.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
@@ -77,12 +68,12 @@ o/%.a:
@$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@)
o/%.pkg:
$(file >$(TMPDIR)/$(subst /,_,$@).args,$(filter %.o,$^))
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPDIR)/$(subst /,_,$@)
$(file >$(TMPSAFE).args,$(filter %.o,$^))
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
o/$(MODE)/%.pkg:
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter %.o,$^))
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPDIR)/$(subst /,_,$@)
$(file >$(TMPSAFE).args,$(filter %.o,$^))
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
@@ -101,18 +92,86 @@ o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/as
@$(COMPILE) -wAASSIMILATE -T$@ o/$(MODE)/tool/build/assimilate.com $@
################################################################################
# strict header checking
# these rules are unsandboxed since they're kind of a sandboxing test themselves
# LOCAL UNIT TESTS
#
# We always run unit tests as part of the normal `make` invocation. you
# may override the $(TESTARGS) variable to do things such as enable the
# benchmarking feature. For example:
#
# TESTARGS = -b
#
# May be specified in your ~/.cosmo.mk file. You can also use this to
# enable things like function tracing. For example:
#
# TESTARGS = ----ftrace
# .PLEDGE += prot_exec
#
# You could then run a command like:
#
# make -j8 o//test/libc/calls/openbsd_test.com.runs
#
# You need PROT_EXEC permission since ftrace morphs the binary. It's
# also worth mentioning that the pledge.com command can simulate what
# Landlock Make does:
#
# o//tool/build/pledge.com \
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
# o//test/libc/calls/openbsd_test.com \
# ----ftrace
#
# This is useful in the event a test binary should run by itself, but
# fails to run beneath Landlock Make. It's also useful sometimes to
# override the verbosity when running tests:
#
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.com.runs
#
# This way, if for some reason a test should fail but calls exit(0),
# then the stdout/stderr output, which would normally be suppressed,
# will actually be displayed.
o/%.h.ok: .UNSANDBOXED = 1
o/$(MODE)/%.runs: o/$(MODE)/%
@$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
################################################################################
# ELF ZIP FILES
#
# zipobj.com lets us do fast incremental linking of compressed data.
# it's nice because if we link a hundred binaries that use the time zone
# database, then that database only needs to be DEFLATE'd once.
o/%.zip.o: o/%
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%.zip.o: %
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
o/$(MODE)/%.zip.o: %
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
# an issue with sandboxing arises when creating directory entries in the
# zip file. we need the trailing slash (e.g. o//foo/.zip.o) but Landlock
# Make avoids sandboxing directory names that have a trailing slash (so
# they can be used to watch for deleted files, without creating overly
# broad unveiling). such rules need to be written more explicitly.
o/$(MODE)%/.zip.o: %
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
################################################################################
# STRICT HEADER CHECKING
#
# these rules are unsandboxed since they're already a sandboxing test,
# and it would be too costly in terms of make latency to have every
# header file depend on $(HDRS) and $(INCS).
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 $@ $<
@@ -120,6 +179,47 @@ 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 $@ $<
################################################################################
# EXECUTABLE HELPERS
MAKE_OBJCOPY = \
$(COMPILE) -AOBJCOPY -T$@ \
$(OBJCOPY) -S -O binary $< $@
MAKE_SYMTAB_CREATE = \
$(COMPILE) -wASYMTAB \
o/$(MODE)/tool/build/symtab.com \
-o $(TMPSAFE)/.symtab \
$<
MAKE_SYMTAB_ZIP = \
$(COMPILE) -AZIP -T$@ \
o/$(MODE)/third_party/zip/zip.com \
-b$(TMPDIR) \
-9qj \
$@ \
$(TMPSAFE)/.symtab
################################################################################
# EMACS ASSEMBLY GENERATION
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: private .UNSANDBOXED = 1
o/$(MODE)/%-gcc.asm: %.cc
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
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: private .UNSANDBOXED = 1
o/$(MODE)/%-clang.asm: %.cc
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
+2 -2
View File
@@ -67,7 +67,7 @@ plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done) {
plm_buffer_t *plm_buffer_create_with_memory(unsigned char *bytes, size_t length, int free_when_done) {
plm_buffer_t *b;
b = memalign(alignof(plm_buffer_t), sizeof(plm_buffer_t));
b = memalign(_Alignof(plm_buffer_t), sizeof(plm_buffer_t));
memset(b, 0, sizeof(plm_buffer_t));
b->capacity = length;
b->length = length;
@@ -79,7 +79,7 @@ plm_buffer_t *plm_buffer_create_with_memory(unsigned char *bytes, size_t length,
plm_buffer_t * plm_buffer_create_with_capacity(size_t capacity) {
plm_buffer_t *b;
b = memalign(alignof(plm_buffer_t), sizeof(plm_buffer_t));
b = memalign(_Alignof(plm_buffer_t), sizeof(plm_buffer_t));
memset(b, 0, sizeof(plm_buffer_t));
b->capacity = capacity;
b->free_when_done = true;
+1 -1
View File
@@ -277,7 +277,7 @@ void plm_audio_read_samples(plm_audio_t *self, int ch, int sb, int part);
void plm_audio_matrix_transform(int s[32][3], int ss, float *d, int dp);
plm_audio_t *plm_audio_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
plm_audio_t *self = (plm_audio_t *)memalign(alignof(plm_audio_t), sizeof(plm_audio_t));
plm_audio_t *self = (plm_audio_t *)memalign(_Alignof(plm_audio_t), sizeof(plm_audio_t));
memset(self, 0, sizeof(plm_audio_t));
self->samples.count = PLM_AUDIO_SAMPLES_PER_FRAME;
+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);
+5 -4
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 */
@@ -97,8 +98,8 @@ static relegated void ttyraw_onsig(int sig, struct siginfo *info,
}
for (i = 0; i < ARRAYLEN(g_ttyraw.sigs); ++i) {
if (g_ttyraw.sigs[i] == sig) {
if (g_ttyraw.next[i] != SIG_IGN) {
if (g_ttyraw.next[i] != SIG_DFL) {
if (g_ttyraw.next[i] != (void *)SIG_IGN) {
if (g_ttyraw.next[i] != (void *)SIG_DFL) {
if (g_ttyraw.next[i]) {
g_ttyraw.next[i](sig, info, ctx);
}
@@ -117,7 +118,7 @@ static textstartup void ttyraw_initsig(int sig, unsigned flags, unsigned mask) {
struct sigaction old;
g_ttyraw.next[i] = xsigaction(sig, ttyraw_onsig, flags, mask, &old) != -1
? old.sa_sigaction
: SIG_DFL;
: (void *)SIG_DFL;
g_ttyraw.sigs[i++] = sig;
}
+41
View File
@@ -0,0 +1,41 @@
#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/stdio/stdio.h"
#include "libc/time/time.h"
/**
* @fileoverview clock() function demo
*/
int main(int argc, char *argv[]) {
unsigned long i;
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);
for (;;) {
for (i = 0;; ++i) {
x *= 7;
if (!(i % 256)) {
now = _timespec_mono();
if (_timespec_gte(now, next)) {
break;
}
}
}
next = _timespec_add(next, interval);
printf("consumed %10g seconds monotonic time and %10g seconds cpu time\n",
_timespec_tonanos(_timespec_sub(now, start)) / 1000000000.,
(double)clock() / CLOCKS_PER_SEC);
}
}
+56
View File
@@ -0,0 +1,56 @@
#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_MONOTONIC);
show(CLOCK_MONOTONIC_RAW);
show(CLOCK_MONOTONIC_FAST);
show(CLOCK_MONOTONIC_PRECISE);
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);
}
+2 -1
View File
@@ -8,11 +8,12 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#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 -3
View File
@@ -9,19 +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/intrin/kprintf.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"
@@ -152,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 {
+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"
+6 -5
View File
@@ -7,7 +7,6 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
@@ -15,15 +14,16 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/stdio/rand.h"
#include "libc/runtime/gc.h"
#include "libc/mem/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/append.internal.h"
#include "libc/stdio/append.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/slice.h"
#include "libc/str/str.h"
@@ -40,6 +40,7 @@
#include "libc/sysv/consts/tcp.h"
#include "libc/time/struct/tm.h"
#include "libc/x/x.h"
#include "libc/x/xsigaction.h"
#include "net/http/http.h"
#include "net/http/url.h"
#include "net/https/https.h"
@@ -182,7 +183,7 @@ int main(int argc, char *argv[]) {
struct Url url;
char *host, *port;
bool usessl = false;
_gc(ParseUrl(urlarg, -1, &url));
_gc(ParseUrl(urlarg, -1, &url, kUrlPlus));
_gc(url.params.p);
if (url.scheme.n) {
if (url.scheme.n == 5 && !memcasecmp(url.scheme.p, "https", 5)) {
+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.
+2 -1
View File
@@ -8,9 +8,10 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/assert.h"
#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"
/**
+4
View File
@@ -66,12 +66,14 @@ EXAMPLES_DIRECTDEPS = \
LIBC_THREAD \
LIBC_TIME \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
LIBC_ZIPOS \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LIBCXX \
@@ -79,6 +81,8 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_LUA \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_STB \
THIRD_PARTY_XED \
+1 -9
View File
@@ -8,21 +8,13 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/nt/process.h"
#include "libc/stdio/rand.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.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 -6
View File
@@ -7,12 +7,11 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/math.h"
#include "libc/stdio/stdio.h"
#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");
}
+4 -14
View File
@@ -7,19 +7,9 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/fmt/itoa.h"
#include "libc/runtime/sysconf.h"
#include "libc/stdio/stdio.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
int main(int argc, char *argv[]) {
int c, n;
char a[22], *p;
if ((c = GetCpuCount())) {
p = FormatInt64(a, c);
*p++ = '\n';
return write(1, a, p - a) == p - a ? 0 : 1;
} else {
return 1;
}
int main() {
kprintf("%d\n", _getcpucount());
}
+5 -4
View File
@@ -7,20 +7,21 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/bits.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 +102,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 +215,7 @@ const struct Function {
{"moby", moby}, //
{"mt19937", _mt19937}, //
{"python", pythonx2}, //
{"rand64", rand64}, //
{"rand64", _rand64}, //
{"rdrand", rdrand}, //
{"rdrnd", rdrand}, //
{"rdseed", rdseed}, //
+22 -20
View File
@@ -8,27 +8,26 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/assert.h"
#include "libc/intrin/atomic.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#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"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/wait0.internal.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/threaded.h"
#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"
@@ -47,6 +46,9 @@
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/tcp.h"
#include "libc/thread/spawn.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/thread/wait0.internal.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "net/http/http.h"
@@ -103,14 +105,14 @@
"Cache-Control: private; max-age=0\r\n"
int threads;
_Atomic(int) workers;
_Atomic(int) messages;
_Atomic(int) listening;
_Atomic(int) connections;
_Atomic(int) closingtime;
atomic_int workers;
atomic_int messages;
atomic_int listening;
atomic_int connections;
atomic_int closingtime;
const char *volatile status;
int Worker(void *id, int tid) {
void *Worker(void *id) {
int server, yes = 1;
// load balance incoming connections for port 8080 across all threads
@@ -134,7 +136,7 @@ int Worker(void *id, int tid) {
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;
}
@@ -164,7 +166,7 @@ int Worker(void *id, int tid) {
// 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
@@ -276,8 +278,8 @@ void PrintStatus(void) {
}
int main(int argc, char *argv[]) {
int i;
struct spawn *th;
int i, rc;
pthread_t *th;
uint32_t *hostips;
// ShowCrashReports();
@@ -296,9 +298,9 @@ 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\n");
kprintf("error: invalid number of threads: %d\n", threads);
exit(1);
}
@@ -309,12 +311,12 @@ int main(int argc, char *argv[]) {
pledge("stdio inet", 0);
// spawn over 9,000 worker threads
th = calloc(threads, sizeof(*th));
th = calloc(threads, sizeof(pthread_t));
for (i = 0; i < threads; ++i) {
++workers;
if (_spawn(Worker, (void *)(intptr_t)i, th + i) == -1) {
if ((rc = pthread_create(th + i, 0, Worker, (void *)(intptr_t)i))) {
--workers;
kprintf("error: _spawn(%d) failed %m\n", i);
kprintf("error: pthread_create(%d) failed %s\n", i, strerror(rc));
}
if (!(i % 500)) {
PrintStatus();
@@ -332,7 +334,7 @@ int main(int argc, char *argv[]) {
// join the workers
for (i = 0; i < threads; ++i) {
_join(th + i);
pthread_join(th[i], 0);
}
// clean up memory
+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},
+6 -4
View File
@@ -8,12 +8,14 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
char hostname[254];
CHECK_NE(-1, gethostname(hostname, sizeof(hostname)));
puts(hostname);
char name[254];
gethostname(name, sizeof(name));
kprintf("gethostname() → %#s\n", name);
getdomainname(name, sizeof(name));
kprintf("getdomainname() → %#s\n", name);
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 {
+6 -5
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,7 +39,8 @@
#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"
@@ -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;
+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"
+1 -2
View File
@@ -8,11 +8,10 @@
╚─────────────────────────────────────────────────────────────────*/
#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"
#include "libc/intrin/kprintf.h"
#include "libc/log/color.internal.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.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
+1 -1
View File
@@ -21,7 +21,7 @@
volatile bool gotalrm;
void OnSigAlrm(int sig, siginfo_t *si, ucontext_t *ctx) {
void OnSigAlrm(int sig, siginfo_t *si, void *ctx) {
gotalrm = true;
}
+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"
/**
+33
View File
@@ -0,0 +1,33 @@
#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/thread/thread.h"
#include "libc/stdio/stdio.h"
/**
* @fileoverview Basic POSIX Threads Example.
*
* $ make -j8 o//examples/thread.com
* $ o//examples/thread.com
* hi there
*
*/
void *worker(void *arg) {
fputs(arg, stdout);
return "there\n";
}
int main() {
void *result;
pthread_t id;
pthread_create(&id, 0, worker, "hi ");
pthread_join(id, &result);
fputs(result, stdout);
}
+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),
+2 -1
View File
@@ -26,8 +26,9 @@
* and this example should work on all supported platforms even Windows
*/
void handler(int sig, siginfo_t *si, ucontext_t *ctx) {
void handler(int sig, siginfo_t *si, void *vctx) {
struct XedDecodedInst xedd;
struct ucontext *ctx = vctx;
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
ctx->uc_mcontext.rip += xedd.length;
+6 -6
View File
@@ -14,11 +14,11 @@
int main(int argc, char *argv[]) {
struct utsname names;
if (uname(&names)) return 1;
printf("%-10s %s\n", "sysname", names.sysname);
printf("%-10s %s\n", "nodename", names.nodename);
printf("%-10s %s\n", "release", names.release);
printf("%-10s %s\n", "version", names.version);
printf("%-10s %s\n", "machine", names.machine);
printf("%-10s %s\n", "domainname", names.domainname);
printf("%-10s %`'s\n", "sysname", names.sysname);
printf("%-10s %`'s\n", "release", names.release);
printf("%-10s %`'s\n", "version", names.version);
printf("%-10s %`'s\n", "machine", names.machine);
printf("%-10s %`'s\n", "nodename", names.nodename);
printf("%-10s %`'s\n", "domainname", names.domainname);
return 0;
}
+439 -359
View File
File diff suppressed because it is too large. Load diff
-143
View File
@@ -1,143 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h"
#include "libc/calls/ttydefaults.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/consts/w.h"
#define STR(s) s, strlen(s)
struct termios tio;
struct winsize wsz;
sigset_t chldmask, savemask;
struct sigaction ignore, saveint, savequit;
char databuf[512];
char pathbuf[PATH_MAX];
int main(int argc, char *argv[]) {
ssize_t rc;
const char *prog;
size_t i, got, wrote;
int ws, mfd, sfd, pid;
if (argc < 2) {
write(2, STR("usage: "));
if (argc > 0) write(2, argv[0], strlen(argv[0]));
write(2, STR(" prog [argv₁...]\n"));
return 1;
}
if (!(prog = commandv(argv[1], pathbuf, sizeof(pathbuf)))) {
write(2, STR("error: "));
write(2, argv[1], strlen(argv[1]));
write(2, STR(" not found\n"));
return 2;
}
bzero(&wsz, sizeof(wsz));
wsz.ws_col = 80;
wsz.ws_row = 45;
bzero(&tio, sizeof(tio));
tio.c_iflag = ICRNL | IXON | IUTF8;
tio.c_oflag = OPOST | ONLCR;
tio.c_cflag = CREAD | CS8;
tio.c_lflag =
ISIG | ICANON | ECHO | ECHOE | ECHOK | IEXTEN | ECHOCTL | ECHOKE;
tio.c_cc[VMIN] = 1;
tio.c_cc[VINTR] = CTRL('C');
tio.c_cc[VQUIT] = CTRL('\\');
tio.c_cc[VERASE] = CTRL('?');
tio.c_cc[VKILL] = CTRL('U');
tio.c_cc[VEOF] = CTRL('D');
tio.c_cc[VSTART] = CTRL('Q');
tio.c_cc[VSTOP] = CTRL('S');
tio.c_cc[VSUSP] = CTRL('Z');
tio.c_cc[VREPRINT] = CTRL('R');
tio.c_cc[VDISCARD] = CTRL('O');
tio.c_cc[VWERASE] = CTRL('W');
tio.c_cc[VLNEXT] = CTRL('V');
if (openpty(&mfd, &sfd, 0, &tio, &wsz)) {
write(2, STR("error: openpty() failed\n"));
return 3;
}
ignore.sa_flags = 0;
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
sigaction(SIGINT, &ignore, &saveint);
sigaction(SIGQUIT, &ignore, &savequit);
sigemptyset(&chldmask);
sigaddset(&chldmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
if ((pid = vfork()) == -1) {
write(2, STR("error: vfork() failed\n"));
return 4;
}
if (!pid) {
close(0);
dup(sfd);
close(1);
dup(sfd);
close(2);
dup(sfd);
close(mfd);
sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0);
sigprocmask(SIG_SETMASK, &savemask, 0);
execv(prog, argv + 1);
return 127;
}
close(sfd);
for (;;) {
if (waitpid(pid, &ws, WNOHANG) == pid) {
break;
}
rc = read(mfd, databuf, sizeof(databuf));
if (rc == -1) {
perror("read");
return 5;
}
if (!(got = rc)) {
continue;
}
for (i = 0; i < got; i += wrote) {
rc = write(1, databuf + i, got - i);
if (rc != -1) {
wrote = rc;
} else {
write(2, STR("error: read() failed\n"));
return 5;
}
}
}
sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0);
sigprocmask(SIG_SETMASK, &savemask, 0);
if (WIFEXITED(ws)) {
return WEXITSTATUS(ws);
} else {
return 128 + WTERMSIG(ws);
}
}
+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);
}
}
}
+33
View File
@@ -0,0 +1,33 @@
#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");
int main(int argc, char *argv[]) {
volatile int x = 1;
volatile int y = 2;
printf("\e[92;44mHello World!\e[0m %d\n", 1 / (x + y - 3));
for (;;);
}
-4
View File
@@ -7,16 +7,12 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/s.h"
#include "libc/x/x.h"
#include "third_party/musl/ftw.h"
/**
+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);
}
+57 -3
View File
@@ -7,16 +7,70 @@ extern bool __assert_disable;
void __assert_fail(const char *, const char *, int) hidden 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__
#ifndef TINY
/**
* 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 -39
View File
@@ -1,21 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_ATOMIC_H_
#define COSMOPOLITAN_LIBC_ATOMIC_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)
@@ -27,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
@@ -75,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_ */
+27
View File
@@ -0,0 +1,27 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/struct/cpuset.h"
#include "libc/macros.internal.h"
void CPU_AND(cpu_set_t *d, cpu_set_t *x, cpu_set_t *y) {
int i;
for (i = 0; i < ARRAYLEN(d->__bits); ++i) {
d->__bits[i] = x->__bits[i] & y->__bits[i];
}
}
+29
View File
@@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/struct/cpuset.h"
#include "libc/intrin/popcnt.h"
#include "libc/macros.internal.h"
int CPU_COUNT(cpu_set_t *set) {
int i, c;
for (c = i = 0; i < ARRAYLEN(set->__bits); ++i) {
c += popcnt(set->__bits[i]);
}
return c;
}
+24
View File
@@ -0,0 +1,24 @@
/*-*- 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/struct/cpuset.h"
#include "libc/str/str.h"
int CPU_EQUAL(cpu_set_t *x, cpu_set_t *y) {
return !memcmp(x, y, sizeof(*x));
}
+27
View File
@@ -0,0 +1,27 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/struct/cpuset.h"
#include "libc/macros.internal.h"
void CPU_OR(cpu_set_t *d, cpu_set_t *x, cpu_set_t *y) {
int i;
for (i = 0; i < ARRAYLEN(d->__bits); ++i) {
d->__bits[i] = x->__bits[i] | y->__bits[i];
}
}
+27
View File
@@ -0,0 +1,27 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/struct/cpuset.h"
#include "libc/macros.internal.h"
void CPU_XOR(cpu_set_t *d, cpu_set_t *x, cpu_set_t *y) {
int i;
for (i = 0; i < ARRAYLEN(d->__bits); ++i) {
d->__bits[i] = x->__bits[i] ^ y->__bits[i];
}
}
+5 -7
View File
@@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ Copyright 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 │
@@ -16,11 +16,9 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/log/bsd.h"
#include "libc/calls/struct/cpuset.h"
#include "libc/str/str.h"
void(warn)(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
(vwarn)(fmt, va);
va_end(va);
void CPU_ZERO(cpu_set_t *set) {
bzero(set, sizeof(*set));
}
@@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2021 Justine Alexandra Roberts Tunney │
│ 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 │
@@ -16,6 +16,6 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/log/libfatal.internal.h"
#include "libc/calls/sig.internal.h"
char __fatalbuf[FRAMESIZE];
struct Signals __sig;
+75 -33
View File
@@ -16,26 +16,22 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/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/intrin/spinlock.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 +57,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 +78,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 +86,6 @@ static textwindows struct Signal *__sig_remove(void) {
}
res->next = 0;
break;
} else {
STRACE("%G is masked", res->sig);
}
}
__sig_unlock();
@@ -117,7 +123,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
// 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 +140,11 @@ 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);
__sig_lock();
if (__sighandrvas[sig] == (int32_t)(intptr_t)SIG_DFL) {
__sighandrvas[sig] = rva;
}
__sig_unlock();
}
if (!restartable) {
@@ -150,7 +160,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 +178,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 +204,17 @@ 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;
__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,10 +223,10 @@ 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) {
if (1 <= sig && sig <= 64) {
__sig_lock();
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
STRACE("ignoring %G", sig);
@@ -229,6 +235,7 @@ textwindows int __sig_add(int sig, int si_code) {
STRACE("enqueuing %G", sig);
++__sig_count;
if ((mem = __sig_alloc())) {
mem->tid = tid;
mem->sig = sig;
mem->si_code = si_code;
mem->next = __sig.queue;
@@ -246,7 +253,7 @@ textwindows int __sig_add(int sig, int si_code) {
}
/**
* Enqueues generic signal for delivery on New Technology.
* Checks for unblocked signals and delivers them on New Technology.
*
* @param restartable is for functions like read() but not poll()
* @return true if EINTR should be returned by caller
@@ -264,3 +271,38 @@ textwindows bool __sig_check(bool restartable) {
}
return delivered;
}
/**
* Determines if a signal should be ignored and if so discards existing
* instances of said signal on New Technology.
*
* Even blocked signals are discarded.
*
* @param sig the signal number to remove
* @threadsafe
*/
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_is_fatal(sig))) {
return;
}
if (__sig.queue) {
__sig_lock();
for (prev = 0, cur = __sig.queue; cur; cur = next) {
next = cur->next;
if (sig == cur->sig) {
if (cur == __sig.queue) {
__sig.queue = cur->next;
} else if (prev) {
prev->next = cur->next;
}
__sig_handle(false, cur->sig, cur->si_code, 0);
__sig_free(cur);
} else {
prev = cur;
}
}
__sig_unlock();
}
}
+20 -27
View File
@@ -17,44 +17,37 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.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
/**
* 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] &= ~(SIGKILL | SIGSTOP);
x &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP) | GetSigBit(SIGABRT));
*mask = x;
}
__sig_unlock();
return 0;
} else {
return einval();
+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();
}
}
File renamed without changes.
+30
View File
@@ -0,0 +1,30 @@
/*-*- 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/struct/timespec.h"
/**
* Compares nanosecond timestamps.
*/
int _timespec_cmp(struct timespec a, struct timespec b) {
int cmp;
if (!(cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec))) {
cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
}
return cmp;
}
+29
View File
@@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/struct/timespec.h"
/**
* Converts timespec interval from nanoseconds.
*/
struct timespec _timespec_fromnanos(int64_t x) {
struct timespec ts;
ts.tv_sec = x / 1000000000;
ts.tv_nsec = x % 1000000000;
return ts;
}
+37
View File
@@ -0,0 +1,37 @@
/*-*- 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/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
/**
* Returns high-precision timestamp, the C11 way.
*
* @param ts receives `CLOCK_REALTIME` timestamp
* @param base must be `TIME_UTC`
* @return `base` on success, or `0` on failure
* @see _timespec_real()
*/
int timespec_get(struct timespec *ts, int base) {
if (base == TIME_UTC && !clock_gettime(CLOCK_REALTIME, ts)) {
return base;
} else {
return 0;
}
}
+36
View File
@@ -0,0 +1,36 @@
/*-*- 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/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
/**
* Returns high-precision timestamp granularity, the C23 way.
*
* @param ts receives granularity as a relative timestamp
* @param base must be `TIME_UTC`
* @return `base` on success, or `0` on failure
*/
int timespec_getres(struct timespec *ts, int base) {
if (base == TIME_UTC && !clock_getres(CLOCK_REALTIME, ts)) {
return base;
} else {
return 0;
}
}
File renamed without changes.
+8 -5
View File
@@ -19,13 +19,16 @@
#include "libc/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/nr.h"
#include "libc/time/time.h"
/**
* Returns current monotonic time.
*
* This function uses a `CLOCK_MONOTONIC` clock and never fails.
*
* @see _timespec_real()
*/
struct timespec _timespec_mono(void) {
int ax, dx;
struct timespec ts;
ax = clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
assert(!ax);
_npassert(!clock_gettime(CLOCK_MONOTONIC_FAST, &ts));
return ts;
}
+10 -5
View File
@@ -19,13 +19,18 @@
#include "libc/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/nr.h"
#include "libc/time/time.h"
/**
* Returns current time.
*
* This function uses a `CLOCK_REALTIME` clock and never fails. Unlike
* clock_gettime() or timespec_real() this interface avoids the use of
* pointers which lets time handling code become more elegant.
*
* @see _timespec_mono()
*/
struct timespec _timespec_real(void) {
int ax, dx;
struct timespec ts;
ax = clock_gettime(CLOCK_REALTIME_FAST, &ts);
assert(!ax);
_npassert(!clock_gettime(CLOCK_REALTIME_FAST, &ts));
return ts;
}
+38
View File
@@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 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/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/sysv/consts/clock.h"
/**
* Sleeps for specified delay.
*
* @return unslept time which may be non-zero if the call was interrupted
*/
struct timespec _timespec_sleep(struct timespec delay) {
int rc;
struct timespec remain;
if (!(rc = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
return (struct timespec){0};
} else {
_npassert(rc == EINTR);
return remain;
}
}
+35
View File
@@ -0,0 +1,35 @@
/*-*- 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/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/timer.h"
/**
* Sleeps until the specified time.
*
* @return 0 on success, or EINTR if interrupted
*/
int _timespec_sleep_until(struct timespec abs_deadline) {
int rc;
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
_npassert(!rc || rc == EINTR);
return rc;
}
@@ -21,12 +21,12 @@
/**
* Subtracts two nanosecond timestamps.
*/
struct timespec _timespec_sub(struct timespec x, struct timespec y) {
x.tv_sec -= y.tv_sec;
x.tv_nsec -= y.tv_nsec;
if (x.tv_nsec < 0) {
x.tv_nsec += 1000000000;
x.tv_sec -= 1;
struct timespec _timespec_sub(struct timespec a, struct timespec b) {
a.tv_sec -= b.tv_sec;
if (a.tv_nsec < b.tv_nsec) {
a.tv_nsec += 1000000000;
a.tv_sec--;
}
return x;
a.tv_nsec -= b.tv_nsec;
return a;
}
Loaded 100 of 3332 files, more files were not shown because too many files have changed in this diff. Show more