mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 08:08:04 -10:00
Compare commits
243
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ace523c79b | ||
|
|
c70422586a | ||
|
|
cabb0a7ede | ||
|
|
38aece42ba | ||
|
|
f66ef5d58e | ||
|
|
0c6581f912 | ||
|
|
d522a88def | ||
|
|
795d6fd6cd | ||
|
|
d3a735702b | ||
|
|
214e3a68a9 | ||
|
|
3d0347e26e | ||
|
|
bc464a8898 | ||
|
|
59e1c245d1 | ||
|
|
916f19eea1 | ||
|
|
5029e20bef | ||
|
|
968474d291 | ||
|
|
228fb7428b | ||
|
|
1e5bd4d23e | ||
|
|
fe29710e4e | ||
|
|
579b597ded | ||
|
|
e963d9c8e3 | ||
|
|
9b29358511 | ||
|
|
71273bc5c9 | ||
|
|
1aa0df696c | ||
|
|
a22f0736d8 | ||
|
|
b420ed8248 | ||
|
|
20bb8db9f8 | ||
|
|
a2e443edd7 | ||
|
|
9454788223 | ||
|
|
31a37aeb1a | ||
|
|
79ba5233db | ||
|
|
d26d7ae0e4 | ||
|
|
ee7e296339 | ||
|
|
3bfb7580c5 | ||
|
|
b703eee96e | ||
|
|
5a441ea57f | ||
|
|
10aade69e3 | ||
|
|
53b9f83e1c | ||
|
|
d86027fe90 | ||
|
|
798d542f15 | ||
|
|
295b3d6ca5 | ||
|
|
f9eae9794a | ||
|
|
98f330b764 | ||
|
|
5ef64dbcdb | ||
|
|
0c4c56ff39 | ||
|
|
75fc601ff5 | ||
|
|
28a592f2d4 | ||
|
|
d8faadf44e | ||
|
|
4daafef63a | ||
|
|
2bc0901ce3 | ||
|
|
6bbb44c165 | ||
|
|
0cdba6878b | ||
|
|
1f766a332f | ||
|
|
aeeb851422 | ||
|
|
55a15c204e | ||
|
|
b142ea7176 | ||
|
|
fd76fa0016 | ||
|
|
533f3d1ef1 | ||
|
|
df8ab0aa0c | ||
|
|
344d2dc356 | ||
|
|
f7b4804251 | ||
|
|
64d87d4e5a | ||
|
|
0b317523a0 | ||
|
|
a73e808b25 | ||
|
|
3ac6576fe5 | ||
|
|
312ccc919b | ||
|
|
ea83cc0ad0 | ||
|
|
398f0c16fb | ||
|
|
f3e28aa192 | ||
|
|
8c4cce043c | ||
|
|
98c674d915 | ||
|
|
e99a4dcc8c | ||
|
|
c002e4ba76 | ||
|
|
fe881982b5 | ||
|
|
4178896aa0 | ||
|
|
3641e99042 | ||
|
|
45d72920ba | ||
|
|
feb0f9fb3a | ||
|
|
cc9366b200 | ||
|
|
c89bc56f6a | ||
|
|
36b2710e1a | ||
|
|
e51034bab3 | ||
|
|
f8b9bd2b47 | ||
|
|
0ecd71f697 | ||
|
|
c0bec24fa2 | ||
|
|
58fb2fb3d3 | ||
|
|
8d5f60a9cd | ||
|
|
0ea2907730 | ||
|
|
cfbd2afc19 | ||
|
|
a7bd4ed9ea | ||
|
|
300876ee50 | ||
|
|
e6b22f1f65 | ||
|
|
d6873f637f | ||
|
|
74200a0ea0 | ||
|
|
87222aad35 | ||
|
|
053ee714bd | ||
|
|
8e69cf133a | ||
|
|
3fe7b95fd0 | ||
|
|
014d4bdab2 | ||
|
|
a68cc690ff | ||
|
|
5a6c0f27c3 | ||
|
|
2d79ab6c15 | ||
|
|
5144c22189 | ||
|
|
86ab24ce56 | ||
|
|
cc1920749e | ||
|
|
1beeb7a829 | ||
|
|
d0ac995dc0 | ||
|
|
19bd27358a | ||
|
|
1ba33d233c | ||
|
|
fd0eefce17 | ||
|
|
4d8f884e76 | ||
|
|
4ce5664c4b | ||
|
|
98c53ae526 | ||
|
|
1f87640d17 | ||
|
|
e4ef38403b | ||
|
|
87d7010495 | ||
|
|
29cb53881e | ||
|
|
8d7d00af3a | ||
|
|
9504ebaf7e | ||
|
|
8b08e81a07 | ||
|
|
a3ccc5af1f | ||
|
|
f271ffcf90 | ||
|
|
88806b79b1 | ||
|
|
eb08b9fbeb | ||
|
|
248c6d54bb | ||
|
|
05350eca60 | ||
|
|
f721d61b54 | ||
|
|
cd2f984ec2 | ||
|
|
b3a08d9286 | ||
|
|
067c14891f | ||
|
|
b8f38cf55d | ||
|
|
7cbc2bc083 | ||
|
|
1a3d22b2fd | ||
|
|
3057315a1b | ||
|
|
6a8c21269f | ||
|
|
b3838173ec | ||
|
|
4864565198 | ||
|
|
221817e537 | ||
|
|
690be544da | ||
|
|
919b6fec10 | ||
|
|
644f290035 | ||
|
|
4577f7fe11 | ||
|
|
1b5a5719c3 | ||
|
|
b9187061a7 | ||
|
|
e56a9d0e23 | ||
|
|
2d34819779 | ||
|
|
6215c91e90 | ||
|
|
af59806a42 | ||
|
|
01e6b3ad8d | ||
|
|
daa32d27d4 | ||
|
|
84001a246c | ||
|
|
1f2288be6e | ||
|
|
fabf7f9f02 | ||
|
|
cef08d47b6 | ||
|
|
41801c9802 | ||
|
|
1966369e8e | ||
|
|
3aa8983ec1 | ||
|
|
c029e83dd8 | ||
|
|
472b95fea3 | ||
|
|
dc6d11a031 | ||
|
|
b107d2709f | ||
|
|
4effa23528 | ||
|
|
26ac6871da | ||
|
|
bf03b2e64c | ||
|
|
69c508729e | ||
|
|
7ed524ca31 | ||
|
|
052682c2c0 | ||
|
|
8a91518633 | ||
|
|
8f52c0d773 | ||
|
|
1fbfbb3192 | ||
|
|
f40f97bd07 | ||
|
|
24d79599cc | ||
|
|
da8a08fd58 | ||
|
|
59575f7e80 | ||
|
|
6c16f208b5 | ||
|
|
bb96099c65 | ||
|
|
2584a86ab4 | ||
|
|
9e98d6893d | ||
|
|
6682013d12 | ||
|
|
83abd68029 | ||
|
|
7abca1531f | ||
|
|
7dc8973567 | ||
|
|
1753b669cf | ||
|
|
ae300d0c40 | ||
|
|
c6f75bf95a | ||
|
|
52565e7af3 | ||
|
|
3c19b6e352 | ||
|
|
a1677d605a | ||
|
|
dcbd2b8668 | ||
|
|
4d21cd315d | ||
|
|
da36e7e256 | ||
|
|
09bcfa23d5 | ||
|
|
6b90ff60cd | ||
|
|
2f41b4dcc6 | ||
|
|
5af25f687a | ||
|
|
9c81729008 | ||
|
|
8a236433a2 | ||
|
|
ab64ef7364 | ||
|
|
4177489762 | ||
|
|
4e93750afd | ||
|
|
ca88ce5026 | ||
|
|
6388ef21f8 | ||
|
|
7ffeb29bfc | ||
|
|
da4dffccc5 | ||
|
|
807706a099 | ||
|
|
83d0c3b870 | ||
|
|
6cd1037692 | ||
|
|
e0566c9675 | ||
|
|
3f35b37b68 | ||
|
|
67c27d9e6e | ||
|
|
2a3037d4e8 | ||
|
|
0a61fe4ea0 | ||
|
|
33e8fc8687 | ||
|
|
0ad609268f | ||
|
|
816b0e1851 | ||
|
|
2bd1e72d5a | ||
|
|
5ce83b08c8 | ||
|
|
5f088cec23 | ||
|
|
a8945714e8 | ||
|
|
8a6ac6dd63 | ||
|
|
f5da4efcaf | ||
|
|
b16b332539 | ||
|
|
4d3195f57a | ||
|
|
aad841610e | ||
|
|
7583b3accc | ||
|
|
06a4e2d29b | ||
|
|
67b9675c81 | ||
|
|
4d4aa9e791 | ||
|
|
813e11b90b | ||
|
|
fb7b7c6e21 | ||
|
|
d769df3482 | ||
|
|
c3ed8d6c7f | ||
|
|
937d921018 | ||
|
|
bfef17eb6d | ||
|
|
11ec99931b | ||
|
|
cfd453d125 | ||
|
|
6fa049c9c7 | ||
|
|
3364fc5b03 | ||
|
|
f064183646 | ||
|
|
e26bdbec52 | ||
|
|
5141d00992 | ||
|
|
b9f73e6a4d | ||
|
|
43b2475aaa |
No files matched your search
@@ -0,0 +1,3 @@
|
||||
# -*- conf -*-
|
||||
/build/bootstrap/*.com binary
|
||||
/usr/share/zoneinfo/* binary
|
||||
@@ -1,5 +1,10 @@
|
||||
# -*- conf -*-
|
||||
|
||||
/o
|
||||
|
||||
# TODO: Find some way to have Python write to o/
|
||||
__pycache__
|
||||
|
||||
*.tmp
|
||||
/.bochs.log
|
||||
/HTAGS
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
virt: lxd
|
||||
os: linux
|
||||
language: c
|
||||
script: make -j4 V=0
|
||||
notifications:
|
||||
email: false
|
||||
Vendored
+45
-2
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
|
||||
"forcedInclude": ["${workspaceFolder}/.vscode/vscode.h"],
|
||||
"defines": [
|
||||
"libcesque=",
|
||||
@@ -63,6 +62,50 @@
|
||||
"attributeallocalign(x)=",
|
||||
"nullterminated(x)="
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"cStandard": "gnu17",
|
||||
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
|
||||
"compilerArgs": [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-fdebug-prefix-map=${workspaceFolder}=",
|
||||
"-frecord-gcc-switches",
|
||||
"-Wa,-W",
|
||||
"-Wa,-I.",
|
||||
"-Wa,--noexecstack",
|
||||
"-Wa,--nocompress-debug-sections",
|
||||
"-Og",
|
||||
"-g",
|
||||
"-gdescribe-dies",
|
||||
"-msse3",
|
||||
"-mno-red-zone",
|
||||
"-fno-math-errno",
|
||||
"-fno-trapping-math",
|
||||
"-fno-fp-int-builtin-inexact",
|
||||
"-fno-ident",
|
||||
"-fno-common",
|
||||
"-fno-gnu-unique",
|
||||
"-fstrict-aliasing",
|
||||
"-fstrict-overflow",
|
||||
"-fno-semantic-interposition",
|
||||
"-mno-omit-leaf-frame-pointer",
|
||||
"-fno-jump-tables",
|
||||
"-nostdinc",
|
||||
"-iquote."
|
||||
],
|
||||
"forcedInclude": [
|
||||
"libc/integral/normalize.inc"
|
||||
],
|
||||
"defines": [
|
||||
"COSMO",
|
||||
"MODE=",
|
||||
"IMAGE_BASE_VIRTUAL=0x400000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
|
||||
Vendored
-157
@@ -1,159 +1,2 @@
|
||||
#define __VSCODE_INTELLISENSE__ 1
|
||||
#include "libc/integral/normalize.inc"
|
||||
|
||||
#if 0
|
||||
#define __VSCODE_INTELLISENSE__ 1
|
||||
#define __BIGGEST_ALIGNMENT__ 1
|
||||
#define __CHAR_MAX__ 0x7F
|
||||
#define __SCHAR_MAX__ __CHAR_MAX__
|
||||
#define __SHRT_MAX__ 0x7FFF
|
||||
#define __INT_MAX__ 0x7FFFFFFF
|
||||
#define __LONG_MAX__ 0x7FFFFFFFFFFFFFFF
|
||||
#define __LONG_LONG_MAX__ __LONG_MAX__
|
||||
#define __CHAR_MIN__ -((__CHAR_MAX__) + 1)
|
||||
#define __SHRT_MIN__ -((__SHRT_MAX__) + 1)
|
||||
#define __INT_MIN__ -((__INT_MAX__) + 1)
|
||||
#define __LONG_MIN__ -((__LONG_MAX__) + 1)
|
||||
#define __LONG_LONG_MIN__ -((__LONG_LONG_MAX__) + 1)
|
||||
#define __UCHAR_MAX__ 0xFF
|
||||
#define __USHRT_MAX__ 0xFFFF
|
||||
#define __UINT_MAX__ 0xFFFFFFFF
|
||||
#define __ULONG_MAX__ 0xFFFFFFFFFFFFFFFF
|
||||
#define __SIZE_MAX__ __ULONG_MAX__
|
||||
#define __SSIZE_MAX__ __LONG_MAX__
|
||||
#define __UINTPTR_MAX__ __SIZE_MAX__
|
||||
#define __INTPTR_MAX__ __SSIZE_MAX__
|
||||
#define __WCHAR_MAX__ __UINT_MAX__
|
||||
#define __PTRDIFF_MAX__ __UINTPTR_MAX__
|
||||
#define __INTMAX_MAX__ __ULONG_MAX__
|
||||
#define __SIZEOF_POINTER__ 8
|
||||
#define __SIZEOF_SHORT__ 2
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __SIZEOF_LONG__ 8
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __SIZEOF_WCHAR_T__ 4
|
||||
#define __SIZEOF_WINT_T__ 4
|
||||
#define __SIZEOF_FLOAT__ 4
|
||||
#define __SIZEOF_FLOAT128__ 16
|
||||
#define __SIZEOF_DOUBLE__ 8
|
||||
#define __SIZEOF_FLOAT80__ 10
|
||||
#define __SIZEOF_LONG_DOUBLE__ 16
|
||||
#define __FLT_MAX__ 1
|
||||
#define __DBL_MAX__ 1
|
||||
|
||||
#define __INT_LEAST8_TYPE__ signed char
|
||||
#define __INT_LEAST16_TYPE__ signed short
|
||||
#define __INT_LEAST32_TYPE__ signed int
|
||||
#define __INT_LEAST64_TYPE__ signed long long
|
||||
#define __UINT_LEAST8_TYPE__ unsigned char
|
||||
#define __UINT_LEAST16_TYPE__ unsigned short
|
||||
#define __UINT_LEAST32_TYPE__ unsigned int
|
||||
#define __UINT_LEAST64_TYPE__ unsigned long long
|
||||
|
||||
#define __UINT8_MAX__ __UCHAR_MAX__
|
||||
#define __UINT16_MAX__ __USHRT_MAX__
|
||||
#define __UINT32_MAX__ __UINT_MAX__
|
||||
#define __UINT64_MAX__ __ULONG_MAX__
|
||||
|
||||
#define __INT8_MAX__ __CHAR_MAX__
|
||||
#define __INT16_MAX__ __SHRT_MAX__
|
||||
#define __INT32_MAX__ __INT_MAX__
|
||||
#define __INT64_MAX__ __LONG_MAX__
|
||||
|
||||
#define ATEXIT_MAX 1
|
||||
#define STACKSIZE 0x10000
|
||||
#define ARG_MAX 255
|
||||
#define OPEN_MAX 0x7FFF
|
||||
#define CHAR_BIT 7
|
||||
#define NSIG 1
|
||||
#define NULL (0)
|
||||
#define false 0
|
||||
#define true (!(false))
|
||||
#define COSMOPOLITAN_C_START_
|
||||
#define COSMOPOLITAN_C_END_
|
||||
#define PAGESIZE 0x1000
|
||||
#define BIGPAGESIZE 0x10000
|
||||
#define NAME_MAX 255
|
||||
|
||||
#define SWITCHEROO(...) 0
|
||||
|
||||
extern unsigned __log_level;
|
||||
|
||||
typedef void * va_list;
|
||||
|
||||
#define va_start(...) 0
|
||||
#define va_end(...) 0
|
||||
#define va_arg(x, y) (y)(0)
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
#define int64_t long long
|
||||
#define int128_t int64_t
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned long long uint128_t;
|
||||
|
||||
typedef int errno_t;
|
||||
typedef uint64_t size_t;
|
||||
typedef unsigned long long ssize_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef long long intptr_t;
|
||||
|
||||
typedef unsigned long long uintmax_t;
|
||||
typedef long long intmax_t;
|
||||
|
||||
typedef uint32_t bool32;
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef uint8_t bool;
|
||||
typedef uint16_t char16_t;
|
||||
typedef uint32_t char32_t;
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef char32_t wint_t;
|
||||
typedef char32_t wchar_t;
|
||||
typedef struct { int ax, dx; } axdx_t;
|
||||
|
||||
/* duplicate and replace xmmintrin.internal.h to fix it for IntelliSense
|
||||
* SEE: <> */
|
||||
|
||||
#define _Vector_size(x) __attribute__((__vector_size__(x)))
|
||||
|
||||
#define IMAGE_BASE_VIRTUAL 0x400000
|
||||
#define __SIGACTION(...) (0)
|
||||
#define VEIL(x, y) (y)
|
||||
#define STATIC_YOINK(x)
|
||||
#define BUFSIZ 1
|
||||
#define FRAMESIZE 0x10000
|
||||
#define PATH_MAX 252
|
||||
#define concat(x, y, z) 0
|
||||
#define CONCAT(a, b, c, d, e) 0
|
||||
#define shuffle(...) 0
|
||||
#define reverse(x, y) 0
|
||||
#define autotype(x) intptr_t
|
||||
|
||||
#define _Generic_(...) (void*)(0)
|
||||
#define _Generic(...) _Generic_
|
||||
#define _Alignas(...)
|
||||
#define _Section(...)
|
||||
|
||||
#define offsetof(x, y) 0
|
||||
#define INITIALIZER(...) struct _dummy
|
||||
#define __far
|
||||
#define BENCHLOOP(...) 0
|
||||
|
||||
#ifdef __hook
|
||||
#undef __hook
|
||||
#endif /* __hook */
|
||||
|
||||
#ifdef UriKeyval
|
||||
#undef UriKeyval
|
||||
#endif /* UriKeyval */
|
||||
|
||||
#define _Static_assert(...) 0
|
||||
#endif /* 0 */
|
||||
@@ -0,0 +1,62 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
We'd love to accept your patches! Please read this guide first.
|
||||
|
||||
## Copyright Assignment
|
||||
|
||||
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
|
||||
you intend to assign her the copyright to the changes you contribute to
|
||||
Cosmopolitan. Please use the same email address you use for git commits
|
||||
which should only contain original source code from you or other people
|
||||
who are also assigning copyright. Please note that, if you're employed,
|
||||
you may need to get your employer's approval beforehand. If you can not
|
||||
assign copyright due to local laws, then you may alternatively consider
|
||||
disclaiming it using the language in [Unlicense](https://unlicense.org)
|
||||
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
|
||||
|
||||
This is important because we can't produce 12kb single-file executables
|
||||
that comply with license requirements if we have to embed lots of them.
|
||||
Although that's less of an issue depending on the purpose of the files.
|
||||
For example, ownership is much less of a concern in the unit test files
|
||||
so you're encouraged to put your copyright on those, provided it's ISC.
|
||||
|
||||
## Style Guide
|
||||
|
||||
You can use clang-format to automatically format your files:
|
||||
|
||||
```sh
|
||||
clang-format -i -style=file tool/net/redbean.c
|
||||
```
|
||||
|
||||
If you use Emacs this can be automated on save for Cosmopolitan using
|
||||
[tool/emacs/cosmo-format.el]([tool/emacs/cosmo-format.el]).
|
||||
|
||||
### Source Files
|
||||
|
||||
- Must use include paths relative to the root of the repository
|
||||
- Must have comment at top of file documenting copyright and license
|
||||
- Must have notice embedding if not owned by Justine (exception: tests)
|
||||
- May use language extensions that are supported by both GCC and Clang
|
||||
- Should use Google indentation (otherwise use `/* clang-format off */`)
|
||||
- Should use asm() instead of compiler APIs (exception: ctz, clz, memcpy)
|
||||
|
||||
### Header Files
|
||||
|
||||
- Must not have copyright or license comments
|
||||
- Must have once guards (otherwise change `.h` to `.inc`)
|
||||
- Must be ANSI C89 compatible to be included in the amalgamation header
|
||||
- Must include its dependencies (exception: libc/integral/normalize.inc)
|
||||
- Must not define objects (i.e. `cc -c -xc foo.h` will produce empty `.o`)
|
||||
- Should not use typedefs
|
||||
- Should not use forward declarations
|
||||
- Should not include documentation comments
|
||||
- Should not include parameter names in prototypes
|
||||
- Should not pose problems if included by C++ or Assembly sources
|
||||
- Should not declare non-ANSI code, at all, when the user requests ANSI
|
||||
|
||||
### Build Config
|
||||
|
||||
- Must not write files outside `o/`
|
||||
- Must not communicate with Internet
|
||||
- Must not depend on system libraries
|
||||
- Must not depend on system commands (exception: sh, make, gzip, zip)
|
||||
@@ -129,21 +129,28 @@ include libc/libc.mk #─┘
|
||||
include libc/sock/sock.mk #─┐
|
||||
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||
include libc/dns/dns.mk # │ You can communicate with the network
|
||||
include libc/crypto/crypto.mk # │
|
||||
include net/http/http.mk #─┘
|
||||
include third_party/duktape/duktape.mk
|
||||
include third_party/regex/regex.mk
|
||||
include net/http/http.mk # │
|
||||
include third_party/mbedtls/mbedtls.mk # │
|
||||
include net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/third_party.mk
|
||||
include libc/testlib/testlib.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include examples/examples.mk
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/sqlite3/sqlite3.mk
|
||||
include third_party/mbedtls/test/test.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/infozip/infozip.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
include third_party/chibicc/test/test.mk
|
||||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include examples/examples.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/hash/hash.mk
|
||||
@@ -158,7 +165,6 @@ include test/libc/nexgen32e/test.mk
|
||||
include test/libc/runtime/test.mk
|
||||
include test/libc/sock/test.mk
|
||||
include test/libc/bits/test.mk
|
||||
include test/libc/crypto/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/unicode/test.mk
|
||||
include test/libc/calls/test.mk
|
||||
@@ -172,6 +178,7 @@ include test/libc/stdio/test.mk
|
||||
include test/libc/release/test.mk
|
||||
include test/libc/test.mk
|
||||
include test/net/http/test.mk
|
||||
include test/net/https/test.mk
|
||||
include test/net/test.mk
|
||||
include test/tool/build/lib/test.mk
|
||||
include test/tool/build/test.mk
|
||||
@@ -188,13 +195,13 @@ include examples/package/build.mk
|
||||
#-φ-examples/package/new.sh
|
||||
include test/test.mk
|
||||
|
||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||
SRCS = $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||
HDRS = $(foreach x,$(PKGS),$($(x)_HDRS))
|
||||
INCS = $(foreach x,$(PKGS),$($(x)_INCS))
|
||||
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
|
||||
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
|
||||
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||
HDRS := $(foreach x,$(PKGS),$($(x)_HDRS))
|
||||
INCS = $(foreach x,$(PKGS),$($(x)_INCS))
|
||||
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
|
||||
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
|
||||
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||
|
||||
bins: $(BINS)
|
||||
check: $(CHECKS)
|
||||
@@ -205,14 +212,24 @@ tags: TAGS HTAGS
|
||||
o/$(MODE)/.x:
|
||||
@mkdir -p $(@D) && touch $@
|
||||
|
||||
ifneq ($(findstring 4.,,$(MAKE_VERSION)),$(MAKE_VERSION))
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(INCS) $(INCS),$(file >>$@,$(x)))
|
||||
else
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^SRCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^HDRS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^INCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
endif
|
||||
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt
|
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS)
|
||||
@rm -f $@
|
||||
@@ -227,14 +244,13 @@ loc: o/$(MODE)/tool/build/summy.com
|
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_CRYPTO \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_OHMYPLUS \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
LIBC_UNICODE \
|
||||
@@ -243,6 +259,7 @@ COSMOPOLITAN_OBJECTS = \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_MUSL \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_REGEX \
|
||||
LIBC_ALG \
|
||||
LIBC_MEM \
|
||||
@@ -265,8 +282,8 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_SYSV \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NEXGEN32E
|
||||
@@ -276,7 +293,6 @@ COSMOPOLITAN_HEADERS = \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CRYPTO \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
|
||||
@@ -19,32 +19,62 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||
## Getting Started
|
||||
|
||||
If you're doing your development work on Linux or BSD then you need just
|
||||
five files to get started:
|
||||
five files to get started. Here's what you do on Linux:
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.zip
|
||||
unzip cosmopolitan.zip
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-1.0.zip
|
||||
unzip cosmopolitan-amalgamation-1.0.zip
|
||||
printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||
gcc -g -Og -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds \
|
||||
-include cosmopolitan.h crt.o ape.o cosmopolitan.a
|
||||
objcopy -S -O binary hello.com.dbg hello.com
|
||||
./hello.com
|
||||
```
|
||||
|
||||
If you're developing on Windows or MacOS then you need to download an
|
||||
You now have a portable program. Please note that your APE binary will
|
||||
assimilate itself as a conventional resident of your platform after the
|
||||
first run, so it can be fast and efficient for subsequent executions.
|
||||
|
||||
```sh
|
||||
./hello.com
|
||||
bash -c './hello.com' # zsh/fish workaround (we upstreamed patches)
|
||||
```
|
||||
|
||||
So if you intend to copy the binary to Windows or Mac then please do
|
||||
that before you run it, not after.
|
||||
|
||||
### MacOS
|
||||
|
||||
If you're developing on MacOS you can install the GNU compiler
|
||||
collection for x86_64-elf via homebrew:
|
||||
|
||||
```sh
|
||||
brew install x86_64-elf-gcc
|
||||
```
|
||||
|
||||
Then in the above scripts just replace `gcc` and `objcopy` with
|
||||
`x86_64-elf-gcc` and `x86_64-elf-objcopy` to compile your APE binary.
|
||||
|
||||
### Windows
|
||||
|
||||
If you're developing on Windows then you need to download an
|
||||
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
|
||||
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||
tutorial. It's needed because the ELF object format is what makes
|
||||
universal binaries possible.
|
||||
|
||||
Cosmopolitan can also be compiled from source on any Linux distro.
|
||||
## Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any Linux distro. GNU make
|
||||
needs to be installed beforehand. This is a freestanding hermetic
|
||||
repository that bootstraps using a vendored static gcc9 executable.
|
||||
No further dependencies are required.
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-0.2.tar.gz
|
||||
tar xf cosmopolitan-0.2.tar.gz # see releases page
|
||||
cd cosmopolitan-0.2
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-1.0.tar.gz
|
||||
tar xf cosmopolitan-1.0.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
make -j16
|
||||
o//examples/hello.com
|
||||
find o -name \*.com | xargs ls -rShal | less
|
||||
@@ -52,13 +82,14 @@ find o -name \*.com | xargs ls -rShal | less
|
||||
|
||||
## Support Vector
|
||||
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| New Technology | Vista | 2006 |
|
||||
| GNU/Systemd | 2.6.18 | 2007 |
|
||||
| XNU's Not UNIX | 15.6 | 2018 |
|
||||
| FreeBSD | 12 | 2018 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| NetBSD | 9.1 | 2020 |
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| New Technology | Vista | 2006 |
|
||||
| GNU/Systemd | 2.6.18 | 2007 |
|
||||
| XNU's Not UNIX! | 15.6 | 2018 |
|
||||
| FreeBSD | 12 | 2018 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| NetBSD | 9.1 | 2020 |
|
||||
| GNU Make | 3.80 | 2010 |
|
||||
@@ -535,7 +535,53 @@ ape_disk:
|
||||
|
||||
#if SupportsWindows() || SupportsMetal() || SupportsXnu()
|
||||
apesh: .ascii "'\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.
|
||||
// There isn't a one-size-fits-all approach for this, thus we
|
||||
// present two choices.
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
// The default behavior is: to overwrite the header in place.
|
||||
// We prefer this because it's a tiny constant one time cost.
|
||||
// We simply printf a 64-byte header and call execve() again.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
#ifdef APE_BUILDSAFE
|
||||
// This code is intended for binaries in build/bootstrap/. It
|
||||
// causes them to not self-modify since they're checked-in to
|
||||
// version control. It assumes cosmopolitan's build prefix is
|
||||
// being used by convention and that the program has the noop
|
||||
// flag -n which is used to prime the binary.
|
||||
.ascii "if [ ${o##o/} = $o ]; then\n"
|
||||
.ascii " if ! [ o/$o -nt $o ]; then\n"
|
||||
.ascii " mkdir -p o/${o%/*} || exit\n"
|
||||
.ascii " cp -f $o o/$o.$$ || exit\n"
|
||||
.ascii " o/$o.$$ -n || exit\n"
|
||||
.ascii " mv -f o/$o.$$ o/$o || exit\n"
|
||||
.ascii " fi\n"
|
||||
.ascii " exec o/$o \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
#endif
|
||||
#else
|
||||
// The alternative behavior is to copy to $TMPDIR and edit.
|
||||
// This imposes a variety of caveats of its own that should
|
||||
// be considered by the user beforehand, such as whether or
|
||||
// not /tmp is considered trustworthy on a given system, or
|
||||
// if the administrator chose to mount it with noexec. It's
|
||||
// up to the user to decide what's best in those situations
|
||||
// and also note that argv[0] and getauxval(AT_EXECFN) will
|
||||
// change as a result of this, and lastly note we don't try
|
||||
// to cleanup the tmp copies for the sake of efficiency. It
|
||||
// should also be noted that if $0 has directory components
|
||||
// then permission clashes can happen between system users,
|
||||
// since only root is able to set the sticky bit, which can
|
||||
// be addressed simply by overriding the TMPDIR environment
|
||||
.ascii "o=\"${TMPDIR:-/tmp}/$0\"\n"
|
||||
.ascii "if [ ! -e \"$o\" ]; then\n"
|
||||
.ascii "d=\"$o\"\n"
|
||||
.ascii "o=\"$o.$$\"\n"
|
||||
.ascii "mkdir -p \"${o%/*}\" 2>/dev/null\n"
|
||||
.ascii "cp -f \"$0\" \"$o\" || exit 120\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
#if SupportsXnu()
|
||||
.ascii "if [ -d /Applications ]; then\n"
|
||||
.ascii "dd if=\"$o\""
|
||||
@@ -547,7 +593,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.shstub ape_macho_dd_count,2
|
||||
.ascii "\" conv=notrunc 2>/dev/null\n"
|
||||
.ascii "el"
|
||||
#endif
|
||||
#endif /* XNU */
|
||||
.ascii "if exec 7<> \"$o\"; then\n"
|
||||
.ascii "printf '"
|
||||
.ascii "\\177ELF" # 0x0: ⌂ELF
|
||||
@@ -574,19 +620,28 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.ascii "' >&7\n"
|
||||
.ascii "exec 7<&-\n"
|
||||
.ascii "else\n"
|
||||
.ascii "exit 1\n"
|
||||
.ascii "exit 121\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$0\" \"$@\"\n" # etxtbsy tail recursion
|
||||
.ascii "R=$?\n" # architecture optimistic
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "exec \"$0\" \"$@\"\n" # optimistic execution
|
||||
#else
|
||||
.ascii "mv -f \"$o\" \"$d\" 2>/dev/null\n"
|
||||
.ascii "o=\"$d\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "exec \"$o\" \"$@\"\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "R=$?\n"
|
||||
.ascii "\n"
|
||||
.ascii "if [ $R -eq 126 ] && [ \"$(uname -m)\" != x86_64 ]; then\n"
|
||||
.ascii "if Q=\"$(command -v qemu-x86_64)\"; then\n"
|
||||
.ascii "exec \"$Q\" \"$0\" \"$@\"\n"
|
||||
.ascii "exec \"$Q\" \"$o\" \"$@\"\n"
|
||||
.ascii "else\n"
|
||||
.ascii "echo error: need qemu-x86_64 >&2\n"
|
||||
.ascii "fi\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "elif [ $R -eq 127 ]; then\n" # means argv[0] was wrong
|
||||
.ascii " exec \"$o\" \"$@\"\n" # so do a path resolution
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "fi\n"
|
||||
.ascii "exit $R\n"
|
||||
.endobj apesh
|
||||
@@ -826,48 +881,48 @@ ape_macho:
|
||||
@see "The Portable Executable File Format from Top to Bottom",
|
||||
Randy Kath, Microsoft Developer Network Technology Group. */
|
||||
|
||||
// ┌14:Uniprocessor Machine ┌─────────────────────────┐
|
||||
// │┌13:DLL │ PE File Characteristics │
|
||||
// ││┌12:System ├─────────────────────────┤
|
||||
// │││┌11:If Net Run From Swap │ r │ reserved │
|
||||
// ││││┌10:If Removable Run From Swap │ d │ deprecated │
|
||||
// │││││┌9:Debug Stripped │ D │ deprecated with │
|
||||
// ││││││┌8:32bit Machine │ │ extreme prejudice │
|
||||
// │││││││ ┌5:Large Address Aware └───┴─────────────────────┘
|
||||
// │││││││ │ ┌1:Executable
|
||||
// │││││││ │ │┌0:Relocs Stripped
|
||||
// d│││││││dr│Ddd││
|
||||
PEEXE = 0b0000001000100011
|
||||
// ┌14:Uniprocessor Machine ┌─────────────────────────┐
|
||||
// │┌13:DLL │ PE File Characteristics │
|
||||
// ││┌12:System ├─────────────────────────┤
|
||||
// │││┌11:If Net Run From Swap │ r │ reserved │
|
||||
// ││││┌10:If Removable Run From Swap │ d │ deprecated │
|
||||
// │││││┌9:Debug Stripped │ D │ deprecated with │
|
||||
// ││││││┌8:32bit Machine │ │ extreme prejudice │
|
||||
// │││││││ ┌5:Large Address Aware └───┴─────────────────────┘
|
||||
// │││││││ │ ┌1:Executable
|
||||
// │││││││ │ │┌0:Relocs Stripped
|
||||
// d│││││││dr│Ddd││
|
||||
PEEXE = 0b00000001000100011
|
||||
|
||||
// ┌15:TERMINAL_SERVER_AWARE ┌─────────────────────────┐
|
||||
// │┌14:GUARD_CF │ PE DLL Characteristics │
|
||||
// ││┌13:WDM_DRIVER ├─────────────────────────┤
|
||||
// │││┌12:APPCONTAINER │ r │ reserved │
|
||||
// ││││┌11:NO_BIND └───┴─────────────────────┘
|
||||
// │││││┌10:NO_SEH
|
||||
// ││││││┌9:NO_ISOLATION
|
||||
// │││││││┌8:NX_COMPAT
|
||||
// ││││││││┌7:FORCE_INTEGRITY
|
||||
// │││││││││┌6:DYNAMIC_BASE
|
||||
// ││││││││││┌5:HIGH_ENTROPY_VA
|
||||
// │││││││││││rrrrr
|
||||
// ┌15:TERMINAL_SERVER_AWARE ┌─────────────────────────┐
|
||||
// │┌14:GUARD_CF │ PE DLL Characteristics │
|
||||
// ││┌13:WDM_DRIVER ├─────────────────────────┤
|
||||
// │││┌12:APPCONTAINER │ r │ reserved │
|
||||
// ││││┌11:NO_BIND └───┴─────────────────────┘
|
||||
// │││││┌10:NO_SEH
|
||||
// ││││││┌9:NO_ISOLATION
|
||||
// │││││││┌8:NX_COMPAT
|
||||
// ││││││││┌7:FORCE_INTEGRITY
|
||||
// │││││││││┌6:DYNAMIC_BASE
|
||||
// ││││││││││┌5:HIGH_ENTROPY_VA
|
||||
// │││││││││││rrrrr
|
||||
DLLSTD = 0b0000000100100000
|
||||
DLLPIE = 0b0000000001100000
|
||||
DLLEXE = DLLSTD
|
||||
|
||||
// ┌31:Writeable ┌─────────────────────────┐
|
||||
// │┌30:Readable │ PE Section Flags │
|
||||
// ││┌29:Executable ├─────────────────────────┤
|
||||
// │││┌28:Shareable │ o │ for object files │
|
||||
// ││││┌27:Unpageable │ r │ reserved │
|
||||
// │││││┌26:Uncacheable └───┴─────────────────────┘
|
||||
// ││││││┌25:Discardable
|
||||
// │││││││┌24:Contains Extended Relocations
|
||||
// ││││││││ ┌15:Contains Global Pointer (GP) Relative Data
|
||||
// ││││││││ │ ┌7:Contains Uninitialized Data
|
||||
// ││││││││ │ │┌6:Contains Initialized Data
|
||||
// ││││││││ o │ ││┌5:Contains Code
|
||||
// ││││││││┌┴─┐rrrr│ ooror│││rorrr
|
||||
// ┌31:Writeable ┌─────────────────────────┐
|
||||
// │┌30:Readable │ PE Section Flags │
|
||||
// ││┌29:Executable ├─────────────────────────┤
|
||||
// │││┌28:Shareable │ o │ for object files │
|
||||
// ││││┌27:Unpageable │ r │ reserved │
|
||||
// │││││┌26:Uncacheable └───┴─────────────────────┘
|
||||
// ││││││┌25:Discardable
|
||||
// │││││││┌24:Contains Extended Relocations
|
||||
// ││││││││ ┌15:Contains Global Pointer (GP) Relative Data
|
||||
// ││││││││ │ ┌7:Contains Uninitialized Data
|
||||
// ││││││││ │ │┌6:Contains Initialized Data
|
||||
// ││││││││ o │ ││┌5:Contains Code
|
||||
// ││││││││┌┴─┐rrrr│ ooror│││rorrr
|
||||
PETEXT = 0b01110000000000000000000001100000
|
||||
PEDATA = 0b11000000000000000000000011000000
|
||||
PEIMPS = 0b11000000000000000000000001000000
|
||||
@@ -1397,19 +1452,19 @@ long: push $GDT_LONG_DATA
|
||||
jmp *%rax
|
||||
.endfn long
|
||||
|
||||
/* ▄▄▒▀▀▀▀▒▒▄░
|
||||
█████▓▓▄░░░░ ▒▒▄░
|
||||
/* ▄▄▒▀▀▀▀▒▒▄
|
||||
█████▓▓▄░░░░ ▒▒▄
|
||||
▐█▓▓█▓▄█████▓░ ▀▒▄
|
||||
▓█▓▓▓▓▓▓▓▓▓█▓ ░▀▒░
|
||||
░▀▀▓█▓▓▓▓▓▓█▓ ░▀▒▄▄▒▄▄▄▒▒▒▀▀▀▀▀▀▀▀▀▀▀▀▀▀▒▒▄▒
|
||||
░▀▓▓█▓▓▓▓▓▄ ░ ░▀▒▄▄ ▄
|
||||
░▀█▓▓▓▓▓▄░ ░▀▒░ ▄▓▌
|
||||
▀▀▓█▓▓▓▓▓▓█▓ ░▀▒▄▄▒▄▄▄▒▒▒▀▀▀▀▀▀▀▀▀▀▀▀▀▀▒▒▄▒
|
||||
▀▓▓█▓▓▓▓▓▄ ░ ░▀▒▄▄ ▄
|
||||
▀█▓▓▓▓▓▄░ ░▀▒░ ▄▓▌
|
||||
▀█▓▓▓▓▓█▓░ ░▀▄░ ░▄▓██░
|
||||
░▀█▓▓▓▓▓█▄ ░▀▒▄▄▄▄▄▄▄▄▒▀▓█▓█▓░
|
||||
░▀█▓▓▓▓█▓░ ░▄▓█▓▓█▓▄▌
|
||||
░▀█▓▓▓▓▓▄ ▄▄▄▓▓██▓▓▒▒░ ▒▒▄▓█▓▓▓▓█▓
|
||||
▀█▓▓▓▓▓█▄ ░▀▒▄▄▄▄▄▄▄▄▒▀▓█▓█▓░
|
||||
▀█▓▓▓▓█▓░ ░▄▓█▓▓█▓▄▌
|
||||
▀█▓▓▓▓▓▄ ▄▄▄▓▓██▓▓▒▒░ ▒▒▄▓█▓▓▓▓█▓
|
||||
▀█▓▓▓▓▓▓▄▄░ ░▄▄▓██▓▓▓▓▓██████████████▓▓▓▓▓▓█▀
|
||||
▐█▓▓▓▓▓▓▓██▓▓▄▄▄▄▄▄▄▄▄▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████████▓▓▀░
|
||||
▐█▓▓▓▓▓▓▓██▓▓▄▄▄▄▄▄▄▄▄▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████████▓▓▀
|
||||
▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█░ ░░░░░░
|
||||
▄░▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▌
|
||||
█▓▄▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓▀▀▀▀▀▀▀▓█▓▓▓▓▓▓▓▓▓▓▓▓
|
||||
@@ -1437,7 +1492,22 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
test %rax,%rax
|
||||
jz 1f
|
||||
movb $METAL,(%rax)
|
||||
1: xor %eax,%eax
|
||||
1: push $0
|
||||
mov %rsp,%rbp
|
||||
mov .Lenv0(%rip),%rax
|
||||
mov %rax,(%rbp) # envp[0][0]
|
||||
push $0 # argv[0][0]
|
||||
push $0 # auxv[1][1]
|
||||
push $0 # auxv[1][0]
|
||||
push %rbp # auxv[0][1]
|
||||
push $31 # auxv[0][0] AT_EXECFN
|
||||
push $0 # envp[1]
|
||||
push $.Lenv0 # envp[0]
|
||||
push $0 # argv[1]
|
||||
push %rbp # argv[0]
|
||||
push $1 # argc
|
||||
xor %ebp,%ebp
|
||||
xor %eax,%eax
|
||||
xor %ecx,%ecx
|
||||
xor %edx,%edx
|
||||
xor %edi,%edi
|
||||
@@ -1446,20 +1516,10 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
xor %r9d,%r9d
|
||||
xor %r10d,%r10d
|
||||
xor %r11d,%r11d
|
||||
push $0 # auxv[1][1]
|
||||
push $0 # auxv[1][0]
|
||||
push $.Larg0 # auxv[0][1]
|
||||
push $31 # auxv[0][0] AT_EXECFN
|
||||
push $0 # envp[1]
|
||||
push $.Lenv0 # envp[0]
|
||||
push $0 # argv[1]
|
||||
push $.Larg0 # argv[0]
|
||||
push $1 # argc
|
||||
jmp _start
|
||||
.endfn kernel
|
||||
|
||||
.rodata
|
||||
.Larg0: .asciz "ape.com"
|
||||
.Lenv0: .asciz "METAL=1"
|
||||
.previous
|
||||
|
||||
|
||||
+3
-1
@@ -201,6 +201,8 @@ SECTIONS {
|
||||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
KEEP(*(.apesh))
|
||||
KEEP(*(.head2))
|
||||
KEEP(*(.text.head))
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
@@ -375,7 +377,7 @@ SECTIONS {
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
||||
.bss ALIGN(__SIZEOF_POINTER__) : {
|
||||
.bss ALIGN(64) : {
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
|
||||
+14
-1
@@ -19,6 +19,11 @@ APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APE_BUILDSAFE = \
|
||||
$(APE_DEPS) \
|
||||
o/$(MODE)/ape/ape-buildsafe.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
-ALINK.ape \
|
||||
@@ -46,5 +51,13 @@ o/ape/idata.inc: \
|
||||
$(APE_OBJS): $(BUILD_FILES) \
|
||||
ape/ape.mk
|
||||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_NO_MODIFY_SELF $<
|
||||
|
||||
o/$(MODE)/ape/ape-buildsafe.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_BUILDSAFE $<
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE) $(APE_CHECKS)
|
||||
o/$(MODE)/ape: $(APE) \
|
||||
$(APE_CHECKS) \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o
|
||||
-1279
File diff suppressed because it is too large.
Load diff
-1294
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+41
-11
@@ -50,6 +50,8 @@ endif
|
||||
|
||||
# Release Mode
|
||||
#
|
||||
# Follows traditional closed source release binary norms.
|
||||
#
|
||||
# - `make MODE=rel`
|
||||
# - More optimized
|
||||
# - Reasonably small
|
||||
@@ -69,16 +71,45 @@ CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
#
|
||||
# Safer binaries good for backend production serving.
|
||||
#
|
||||
# - `make MODE=asan`
|
||||
# - Memory safety
|
||||
# - Production worthy
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
|
||||
ifeq ($(MODE), asan)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
#
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Zero optimization
|
||||
# - Enables sanitization
|
||||
# - Enables stack canaries
|
||||
# - Enormous binaries (b/c ubsan suboptimalities)
|
||||
# - Enables asan
|
||||
# - Enables ubsan (TODO)
|
||||
# - Stack canaries
|
||||
# - No optimization (TODO)
|
||||
# - Enormous binaries
|
||||
|
||||
ifeq ($(MODE), dbg)
|
||||
|
||||
@@ -91,8 +122,7 @@ CONFIG_CCFLAGS += \
|
||||
-O2
|
||||
|
||||
CONFIG_COPTS += \
|
||||
$(SECURITY_BLANKETS) \
|
||||
$(SANITIZER)
|
||||
-fsanitize=address
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
@@ -113,6 +143,7 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tiny)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -140,6 +171,7 @@ endif
|
||||
# - No portability
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -169,6 +201,7 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinuxbsd)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -197,6 +230,7 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinysysv)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -225,6 +259,7 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinynowin)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -282,11 +317,6 @@ endif
|
||||
# such as MSVC or XCode. You can run your binary objects through a tool
|
||||
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
|
||||
# rollup one header file that'll enable linkage with minimal issues.
|
||||
#
|
||||
# Lastly note that in some cases, such as gc(), there simply isn't any
|
||||
# ANSI workaround available. It's only in cases like that when we'll use
|
||||
# the __asm__() header workaround, rather than simply removing it. We do
|
||||
# however try to do that much less often than mainstream C libraries.
|
||||
|
||||
ifeq ($(MODE), ansi)
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ PWD := $(shell pwd)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
HELLO := $(shell build/hello)
|
||||
TMPDIR := $(shell build/findtmp)
|
||||
COMPILE := $(shell build/getcompile) -V$(shell build/getccversion $(CC))
|
||||
SPAWNER := $(shell build/getcompile) -V$(shell build/getccversion $(CC))
|
||||
COMPILE = $(SPAWNER) $(QUOTA)
|
||||
|
||||
export ADDR2LINE
|
||||
export LC_ALL
|
||||
@@ -181,7 +182,6 @@ DEFAULT_LDLIBS =
|
||||
|
||||
MCA = llvm-mca-10 \
|
||||
-mtriple=x86_64-pc-linux-gnu \
|
||||
-iterations=3 \
|
||||
-instruction-info \
|
||||
-iterations=3 \
|
||||
-all-stats \
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
|
||||
@@ -79,4 +79,7 @@ o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLA
|
||||
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/alg/arraylist2.internal.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
/*-*- 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 The Mbed TLS Contributors │
|
||||
│ │
|
||||
│ Licensed under the Apache License, Version 2.0 (the "License"); │
|
||||
│ you may not use this file except in compliance with the License. │
|
||||
│ You may obtain a copy of the License at │
|
||||
│ │
|
||||
│ http://www.apache.org/licenses/LICENSE-2.0 │
|
||||
│ │
|
||||
│ Unless required by applicable law or agreed to in writing, software │
|
||||
│ distributed under the License is distributed on an "AS IS" BASIS, │
|
||||
│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
|
||||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "third_party/mbedtls/ctr_drbg.h"
|
||||
#include "third_party/mbedtls/debug.h"
|
||||
#include "third_party/mbedtls/entropy.h"
|
||||
#include "third_party/mbedtls/net_sockets.h"
|
||||
#include "third_party/mbedtls/ssl.h"
|
||||
#include "third_party/mbedtls/x509_crt.h"
|
||||
|
||||
STATIC_YOINK("ssl_root_support");
|
||||
|
||||
#define MODE_NONE 0
|
||||
#define MODE_FILE 1
|
||||
#define MODE_SSL 2
|
||||
|
||||
#define DFL_MODE MODE_NONE
|
||||
#define DFL_FILENAME "cert.crt"
|
||||
#define DFL_CA_FILE ""
|
||||
#define DFL_CRL_FILE ""
|
||||
#define DFL_CA_PATH "zip:usr/share/ssl/root"
|
||||
#define DFL_SERVER_NAME "localhost"
|
||||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
#define DFL_PERMISSIVE 0
|
||||
|
||||
#define USAGE_IO \
|
||||
" ca_file=%%s file containing top-level CAs\n" \
|
||||
" ca_path=%%s dir containing top-level CAs\n" \
|
||||
" crl_file=%%s The single CRL file you want to use\n"
|
||||
|
||||
#define USAGE \
|
||||
"\n usage: %s param=<>...\n" \
|
||||
"\n acceptable parameters:\n" \
|
||||
" mode=file|ssl default: none\n" \
|
||||
" filename=%%s default: cert.crt\n" USAGE_IO \
|
||||
" server_name=%%s default: localhost\n" \
|
||||
" server_port=%%d default: 4433\n" \
|
||||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" permissive=%%d default: 0 (disabled)\n" \
|
||||
"\n"
|
||||
|
||||
/*
|
||||
* global options
|
||||
*/
|
||||
struct options {
|
||||
int mode; /* the mode to run the application in */
|
||||
const char *filename; /* filename of the certificate file */
|
||||
const char *ca_file; /* the file with the CA certificate(s) */
|
||||
const char *crl_file; /* the file with the CRL to use */
|
||||
const char *ca_path; /* the path with the CA certificate(s) reside */
|
||||
const char *server_name; /* hostname of the server (client only) */
|
||||
const char *server_port; /* port on which the ssl service runs */
|
||||
int debug_level; /* level of debugging */
|
||||
int permissive; /* permissive parsing */
|
||||
} opt;
|
||||
|
||||
static void my_debug(void *ctx, int level, const char *file, int line,
|
||||
const char *str) {
|
||||
fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str);
|
||||
fflush((FILE *)ctx);
|
||||
}
|
||||
|
||||
static int my_verify(void *data, mbedtls_x509_crt *crt, int depth,
|
||||
uint32_t *flags) {
|
||||
char buf[1024];
|
||||
printf("\nVerify requested for (Depth %d):\n", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
printf("%s", buf);
|
||||
if (*flags) {
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", *flags);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
mbedtls_net_context server_fd;
|
||||
unsigned char buf[1024];
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt cacert;
|
||||
mbedtls_x509_crl cacrl;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret = 1;
|
||||
int exit_code = EXIT_FAILURE;
|
||||
int i, j;
|
||||
uint32_t flags;
|
||||
int verify = 0;
|
||||
char *p, *q;
|
||||
const char *pers = "cert_app";
|
||||
|
||||
/*
|
||||
* Set to sane values
|
||||
*/
|
||||
mbedtls_net_init(&server_fd);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
mbedtls_x509_crt_init(&cacert);
|
||||
#if defined(MBEDTLS_X509_CRL_PARSE_C)
|
||||
mbedtls_x509_crl_init(&cacrl);
|
||||
#else
|
||||
/* Zeroize structure as CRL parsing is not supported and we have to pass
|
||||
it to the verify function */
|
||||
memset(&cacrl, 0, sizeof(mbedtls_x509_crl));
|
||||
#endif
|
||||
|
||||
if (argc == 0) {
|
||||
usage:
|
||||
printf(USAGE, program_invocation_name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
opt.mode = DFL_MODE;
|
||||
opt.filename = DFL_FILENAME;
|
||||
opt.ca_file = DFL_CA_FILE;
|
||||
opt.crl_file = DFL_CRL_FILE;
|
||||
opt.ca_path = DFL_CA_PATH;
|
||||
opt.server_name = DFL_SERVER_NAME;
|
||||
opt.server_port = DFL_SERVER_PORT;
|
||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||
opt.permissive = DFL_PERMISSIVE;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
p = argv[i];
|
||||
if ((q = strchr(p, '=')) == NULL) goto usage;
|
||||
*q++ = '\0';
|
||||
|
||||
for (j = 0; p + j < q; j++) {
|
||||
if (argv[i][j] >= 'A' && argv[i][j] <= 'Z') argv[i][j] |= 0x20;
|
||||
}
|
||||
|
||||
if (strcmp(p, "mode") == 0) {
|
||||
if (strcmp(q, "file") == 0)
|
||||
opt.mode = MODE_FILE;
|
||||
else if (strcmp(q, "ssl") == 0)
|
||||
opt.mode = MODE_SSL;
|
||||
else
|
||||
goto usage;
|
||||
} else if (strcmp(p, "filename") == 0)
|
||||
opt.filename = q;
|
||||
else if (strcmp(p, "ca_file") == 0)
|
||||
opt.ca_file = q;
|
||||
else if (strcmp(p, "crl_file") == 0)
|
||||
opt.crl_file = q;
|
||||
else if (strcmp(p, "ca_path") == 0)
|
||||
opt.ca_path = q;
|
||||
else if (strcmp(p, "server_name") == 0)
|
||||
opt.server_name = q;
|
||||
else if (strcmp(p, "server_port") == 0)
|
||||
opt.server_port = q;
|
||||
else if (strcmp(p, "debug_level") == 0) {
|
||||
opt.debug_level = atoi(q);
|
||||
if (opt.debug_level < 0 || opt.debug_level > 65535) goto usage;
|
||||
} else if (strcmp(p, "permissive") == 0) {
|
||||
opt.permissive = atoi(q);
|
||||
if (opt.permissive < 0 || opt.permissive > 1) goto usage;
|
||||
} else
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1.1. Load the trusted CA
|
||||
*/
|
||||
printf(" . Loading the CA root certificate ...");
|
||||
fflush(stdout);
|
||||
|
||||
if (strlen(opt.ca_path)) {
|
||||
if ((ret = mbedtls_x509_crt_parse_path(&cacert, opt.ca_path)) < 0) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_parse_path returned -0x%x\n\n",
|
||||
(unsigned int)-ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
verify = 1;
|
||||
} else if (strlen(opt.ca_file)) {
|
||||
if ((ret = mbedtls_x509_crt_parse_file(&cacert, opt.ca_file)) < 0) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n",
|
||||
(unsigned int)-ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
verify = 1;
|
||||
}
|
||||
|
||||
printf(" ok (%d skipped)\n", ret);
|
||||
|
||||
#if defined(MBEDTLS_X509_CRL_PARSE_C)
|
||||
if (strlen(opt.crl_file)) {
|
||||
if ((ret = mbedtls_x509_crl_parse_file(&cacrl, opt.crl_file)) != 0) {
|
||||
printf(" failed\n ! mbedtls_x509_crl_parse returned -0x%x\n\n",
|
||||
(unsigned int)-ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
verify = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opt.mode == MODE_FILE) {
|
||||
mbedtls_x509_crt crt;
|
||||
mbedtls_x509_crt *cur = &crt;
|
||||
mbedtls_x509_crt_init(&crt);
|
||||
|
||||
/*
|
||||
* 1.1. Load the certificate(s)
|
||||
*/
|
||||
printf("\n . Loading the certificate(s) ...");
|
||||
fflush(stdout);
|
||||
|
||||
ret = mbedtls_x509_crt_parse_file(&crt, opt.filename);
|
||||
|
||||
if (ret < 0) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_parse_file returned -0x%04x\n\n",
|
||||
-ret);
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (opt.permissive == 0 && ret > 0) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_parse failed to parse %d "
|
||||
"certificates\n\n",
|
||||
ret);
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 1.2 Print the certificate(s)
|
||||
*/
|
||||
while (cur != NULL) {
|
||||
printf(" . Peer certificate information ...\n");
|
||||
ret = mbedtls_x509_crt_info((char *)buf, sizeof(buf) - 1, " ", cur);
|
||||
if (ret == -1) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_info returned -0x%04x\n\n",
|
||||
-ret);
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf("%s\n", buf);
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1.3 Verify the certificate
|
||||
*/
|
||||
if (verify) {
|
||||
printf(" . Verifying X.509 certificate...");
|
||||
|
||||
if ((ret = mbedtls_x509_crt_verify(&crt, &cacert, &cacrl, NULL, &flags,
|
||||
my_verify, NULL)) != 0) {
|
||||
char vrfy_buf[512];
|
||||
|
||||
printf(" failed\n");
|
||||
|
||||
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags);
|
||||
|
||||
printf("%s\n", vrfy_buf);
|
||||
} else
|
||||
printf(" ok\n");
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_free(&crt);
|
||||
} else if (opt.mode == MODE_SSL) {
|
||||
/*
|
||||
* 1. Initialize the RNG and the session data
|
||||
*/
|
||||
printf("\n . Seeding the random number generator...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *)pers,
|
||||
strlen(pers))) != 0) {
|
||||
printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold(opt.debug_level);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2. Start the connection
|
||||
*/
|
||||
printf(" . Connecting to tcp/%s/%s...\n", opt.server_name,
|
||||
opt.server_port);
|
||||
|
||||
if ((ret = mbedtls_net_connect(&server_fd, opt.server_name, opt.server_port,
|
||||
MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
printf(" ! mbedtls_net_connect returned -0x%04x\n\n", -ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 3. Setup stuff
|
||||
*/
|
||||
if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
printf(" ! mbedtls_ssl_config_defaults returned -0x%04x\n\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
|
||||
mbedtls_ssl_conf_verify(&conf, my_verify, NULL);
|
||||
} else
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
printf(" ! mbedtls_ssl_setup returned -0x%04x\n\n", -ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_ssl_set_hostname(&ssl, opt.server_name)) != 0) {
|
||||
printf(" ! mbedtls_ssl_set_hostname returned -0x%04x\n\n", -ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv,
|
||||
NULL);
|
||||
|
||||
/*
|
||||
* 4. Handshake
|
||||
*/
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
printf(" ! mbedtls_ssl_handshake returned -0x%04x\n\n", -ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 5. Print the certificate
|
||||
*/
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
printf(" . Peer certificate information ... skipped\n");
|
||||
#else
|
||||
printf(" . Peer certificate information ...\n");
|
||||
ret = mbedtls_x509_crt_info((char *)buf, sizeof(buf) - 1, " ",
|
||||
mbedtls_ssl_get_peer_cert(&ssl));
|
||||
if (ret == -1) {
|
||||
printf(" failed\n ! mbedtls_x509_crt_info returned -0x%04x\n\n", -ret);
|
||||
goto ssl_exit;
|
||||
}
|
||||
|
||||
printf("%s\n", buf);
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
mbedtls_ssl_close_notify(&ssl);
|
||||
|
||||
ssl_exit:
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
} else
|
||||
goto usage;
|
||||
|
||||
exit_code = MBEDTLS_EXIT_SUCCESS;
|
||||
|
||||
exit:
|
||||
|
||||
mbedtls_net_free(&server_fd);
|
||||
mbedtls_x509_crt_free(&cacert);
|
||||
#if defined(MBEDTLS_X509_CRL_PARSE_C)
|
||||
mbedtls_x509_crl_free(&cacrl);
|
||||
#endif
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
|
||||
mbedtls_exit(exit_code);
|
||||
}
|
||||
+1
-1
@@ -73,7 +73,7 @@ void GetOpts(int argc, char *argv[]) {
|
||||
|
||||
int cp(const char *src, const char *dst) {
|
||||
if (endswith(dst, "/") || isdirectory(dst)) {
|
||||
dst = gc(xasprintf("%s/%s", dst, basename));
|
||||
dst = _gc(xasprintf("%s/%s", dst, basename));
|
||||
}
|
||||
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail;
|
||||
if (copyfile(src, dst, flags) == -1) goto OnFail;
|
||||
|
||||
+8
-73
@@ -7,88 +7,23 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nt/enum/errormodeflags.h"
|
||||
#include "libc/nt/signals.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Demonstrates SEGFAULT via NULL pointer dereference.
|
||||
* @fileoverview How to print backtraces and cpu state on crash.
|
||||
*
|
||||
* In MODE=dbg mode, UBSAN should catch this and display a backtrace.
|
||||
* In most other modes, e.g. MODE=balanced, the oncrash.c sig handler
|
||||
* will either launch GDB or display a very fancy report.
|
||||
*
|
||||
* make -j8 -O MODE=opt o/opt/examples/crashreportdemo.com
|
||||
* o/opt/examples/crashreportdemo.com
|
||||
* make -j8 -O o//examples/crashreport.com
|
||||
* o//examples/crashreport.com
|
||||
*
|
||||
* To prevent the GDB GUI from popping up:
|
||||
*
|
||||
* export GDB=""
|
||||
* make -j8 -O MODE=opt o/opt/examples/crashreportdemo.com
|
||||
* o/opt/examples/crashreportdemo.com
|
||||
* export GDB=
|
||||
* make -j8 -O o//examples/crashreport.com
|
||||
* o//examples/crashreport.com
|
||||
*/
|
||||
|
||||
int boo;
|
||||
|
||||
void boop(void);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int64_t res;
|
||||
volatile int64_t x;
|
||||
showcrashreports();
|
||||
res = 0;
|
||||
|
||||
asm volatile("mov\t$0x1111111111111111,%rax\n\t"
|
||||
"mov\t$0x3333333333333333,%rcx\n\t"
|
||||
"mov\t$0x4444444444444444,%rdx\n\t"
|
||||
"mov\t$0x8888888888888888,%r8\n\t"
|
||||
"mov\t$0x9999999999999999,%r9d\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%r10d\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%r11d\n\t"
|
||||
"mov\t$0x0000000000000000,%rax\n\t"
|
||||
"movd\t%rax,%xmm0\n\t"
|
||||
"mov\t$0x1111111111111111,%rax\n\t"
|
||||
"push\t%rax\n\t"
|
||||
"push\t%rax\n\t"
|
||||
"movdqu\t(%rsp),%xmm1\n\t"
|
||||
"pop\t%rax\n\t"
|
||||
"pop\t%rax\n\t"
|
||||
"mov\t$0x2222222222220022,%rax\n\t"
|
||||
"movd\t%rax,%xmm2\n\t"
|
||||
"mov\t$0x3333333333333333,%rax\n\t"
|
||||
"movd\t%rax,%xmm3\n\t"
|
||||
"mov\t$0x4444444444444444,%rax\n\t"
|
||||
"movd\t%rax,%xmm4\n\t"
|
||||
"mov\t$0x5555555555555555,%rax\n\t"
|
||||
"movd\t%rax,%xmm5\n\t"
|
||||
"mov\t$0x6666666666666666,%rax\n\t"
|
||||
"movd\t%rax,%xmm6\n\t"
|
||||
"mov\t$0x7777777777777777,%rax\n\t"
|
||||
"movd\t%rax,%xmm7\n\t"
|
||||
"mov\t$0x8888888888888888,%rax\n\t"
|
||||
"movd\t%rax,%xmm8\n\t"
|
||||
"mov\t$0x9999999999999999,%rax\n\t"
|
||||
"movd\t%rax,%xmm9\n\t"
|
||||
"mov\t$0xaaaaaaaaaaaaaaaa,%rax\n\t"
|
||||
"movd\t%rax,%xmm10\n\t"
|
||||
"mov\t$0xbbbbbbbbbbbbbbbb,%rax\n\t"
|
||||
"movd\t%rax,%xmm11\n\t"
|
||||
"mov\t$0xcccccccccccccccc,%rax\n\t"
|
||||
"movd\t%rax,%xmm12\n\t"
|
||||
"mov\t$0xdddddddddddddddd,%rax\n\t"
|
||||
"movd\t%rax,%xmm13\n\t"
|
||||
"mov\t$0xeeeeeeeeeeeeeeee,%rax\n\t"
|
||||
"movd\t%rax,%xmm14\n\t"
|
||||
"mov\t$0xffffffffffffffff,%rax\n\t"
|
||||
"movd\t%rax,%xmm15\n\t"
|
||||
"fldpi\n\t"
|
||||
"xor\t%eax,%eax\n\t"
|
||||
"div\t%eax\n\t");
|
||||
|
||||
return res;
|
||||
return 1 / (x = 0);
|
||||
}
|
||||
+2
-3
@@ -14,7 +14,6 @@
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
@@ -32,9 +31,9 @@ int main(int argc, char *argv[]) {
|
||||
ssize_t rc;
|
||||
size_t got, wrote;
|
||||
unsigned char buf[512];
|
||||
struct sigaction saint = {.sa_handler = GotCtrlC};
|
||||
fprintf(stderr, "This echos stdio until Ctrl+C is pressed.\n");
|
||||
CHECK_NE(
|
||||
-1, sigaction(SIGINT, &(struct sigaction){.sa_handler = GotCtrlC}, NULL));
|
||||
CHECK_NE(-1, sigaction(SIGINT, &saint, NULL));
|
||||
for (;;) {
|
||||
rc = read(0, buf, BUFSIZ);
|
||||
if (rc != -1) {
|
||||
|
||||
+362
-63
@@ -8,24 +8,49 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/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/stdio.h"
|
||||
#include "libc/str/slice.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ai.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/sysv/consts/tcp.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/uri.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/url.h"
|
||||
#include "net/https/https.h"
|
||||
#include "net/https/sslcache.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/mbedtls/ctr_drbg.h"
|
||||
#include "third_party/mbedtls/debug.h"
|
||||
#include "third_party/mbedtls/error.h"
|
||||
#include "third_party/mbedtls/pk.h"
|
||||
#include "third_party/mbedtls/ssl.h"
|
||||
#include "third_party/mbedtls/ssl_ticket.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Downloads HTTP URL to stdout.
|
||||
@@ -34,73 +59,347 @@
|
||||
* o//examples/curl.com http://justine.lol/ape.html
|
||||
*/
|
||||
|
||||
#define HasHeader(H) (!!msg.headers[H].a)
|
||||
#define HeaderData(H) (p + msg.headers[H].a)
|
||||
#define HeaderLength(H) (msg.headers[H].b - msg.headers[H].a)
|
||||
#define HeaderEqualCase(H, S) \
|
||||
SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H))
|
||||
|
||||
static bool TuneSocket(int fd, int a, int b, int x) {
|
||||
if (!b) return false;
|
||||
return setsockopt(fd, a, b, &x, sizeof(x)) != -1;
|
||||
}
|
||||
|
||||
static int TlsSend(void *c, const unsigned char *p, size_t n) {
|
||||
int rc;
|
||||
NOISEF("begin send %zu", n);
|
||||
CHECK_NE(-1, (rc = write(*(int *)c, p, n)));
|
||||
NOISEF("end send %zu", n);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) {
|
||||
int r;
|
||||
struct iovec v[2];
|
||||
static unsigned a, b;
|
||||
static unsigned char t[4096];
|
||||
if (a < b) {
|
||||
r = MIN(n, b - a);
|
||||
memcpy(p, t + a, r);
|
||||
if ((a += r) == b) a = b = 0;
|
||||
return r;
|
||||
}
|
||||
v[0].iov_base = p;
|
||||
v[0].iov_len = n;
|
||||
v[1].iov_base = t;
|
||||
v[1].iov_len = sizeof(t);
|
||||
NOISEF("begin recv %zu", n + sizeof(t) - b);
|
||||
CHECK_NE(-1, (r = readv(*(int *)c, v, 2)));
|
||||
NOISEF("end recv %zu", r);
|
||||
if (r > n) b = r - n;
|
||||
return MIN(n, r);
|
||||
}
|
||||
|
||||
static wontreturn void PrintUsage(FILE *f, int rc) {
|
||||
fprintf(f, "usage: %s [-ksvV] URL\n", program_invocation_name);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int sock;
|
||||
ssize_t rc;
|
||||
unsigned long need;
|
||||
struct UriSlice path;
|
||||
size_t i, got, toto, msglen;
|
||||
char buf[1500], host[256], port[7];
|
||||
const char *url, *msg, *pathstr, *crlfcrlf, *contentlength;
|
||||
struct UriSlice us[16];
|
||||
struct Uri u = {.segs.p = us, .segs.n = ARRAYLEN(us)};
|
||||
struct addrinfo *addr, *addrs;
|
||||
if (!NoDebug()) showcrashreports();
|
||||
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
|
||||
|
||||
/*
|
||||
* Read flags.
|
||||
*/
|
||||
int opt;
|
||||
struct Headers {
|
||||
size_t n;
|
||||
char **p;
|
||||
} headers = {0};
|
||||
int method = kHttpGet;
|
||||
bool authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
const char *agent = "hurl/1.o (https://github.com/jart/cosmopolitan)";
|
||||
__log_level = kLogWarn;
|
||||
while ((opt = getopt(argc, argv, "qksvVIX:H:A:")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
case 'q':
|
||||
break;
|
||||
case 'v':
|
||||
++__log_level;
|
||||
break;
|
||||
case 'I':
|
||||
method = kHttpHead;
|
||||
break;
|
||||
case 'A':
|
||||
agent = optarg;
|
||||
break;
|
||||
case 'H':
|
||||
headers.p = realloc(headers.p, ++headers.n * sizeof(*headers.p));
|
||||
headers.p[headers.n - 1] = optarg;
|
||||
break;
|
||||
case 'X':
|
||||
CHECK((method = GetHttpMethod(optarg, strlen(optarg))));
|
||||
break;
|
||||
case 'V':
|
||||
++mbedtls_debug_threshold;
|
||||
break;
|
||||
case 'k':
|
||||
authmode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
break;
|
||||
case 'h':
|
||||
PrintUsage(stdout, EXIT_SUCCESS);
|
||||
default:
|
||||
PrintUsage(stderr, EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get argument.
|
||||
*/
|
||||
const char *urlarg;
|
||||
if (optind == argc) PrintUsage(stderr, EX_USAGE);
|
||||
urlarg = argv[optind];
|
||||
|
||||
/*
|
||||
* Parse URL.
|
||||
*/
|
||||
struct Url url;
|
||||
char *host, *port;
|
||||
bool usessl = false;
|
||||
_gc(ParseUrl(urlarg, -1, &url));
|
||||
_gc(url.params.p);
|
||||
if (url.scheme.n) {
|
||||
if (url.scheme.n == 5 && !memcasecmp(url.scheme.p, "https", 5)) {
|
||||
usessl = true;
|
||||
} else if (!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) {
|
||||
fprintf(stderr, "error: not an http/https url: %s\n", urlarg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (url.host.n) {
|
||||
host = _gc(strndup(url.host.p, url.host.n));
|
||||
if (url.port.n) {
|
||||
port = _gc(strndup(url.port.p, url.port.n));
|
||||
} else {
|
||||
port = usessl ? "443" : "80";
|
||||
}
|
||||
} else {
|
||||
host = "127.0.0.1";
|
||||
port = usessl ? "443" : "80";
|
||||
}
|
||||
if (!IsAcceptableHost(host, -1)) {
|
||||
fprintf(stderr, "error: invalid host: %s\n", urlarg);
|
||||
exit(1);
|
||||
}
|
||||
url.fragment.p = 0, url.fragment.n = 0;
|
||||
url.scheme.p = 0, url.scheme.n = 0;
|
||||
url.user.p = 0, url.user.n = 0;
|
||||
url.pass.p = 0, url.pass.n = 0;
|
||||
url.host.p = 0, url.host.n = 0;
|
||||
url.port.p = 0, url.port.n = 0;
|
||||
if (!url.path.n || url.path.p[0] != '/') {
|
||||
char *p = _gc(xmalloc(1 + url.path.n));
|
||||
mempcpy(mempcpy(p, "/", 1), url.path.p, url.path.n);
|
||||
url.path.p = p;
|
||||
++url.path.n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create HTTP message.
|
||||
*/
|
||||
char *request = 0;
|
||||
appendf(&request,
|
||||
"%s %s HTTP/1.1\r\n"
|
||||
"Host: %s:%s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"User-Agent: %s\r\n",
|
||||
kHttpMethod[method], _gc(EncodeUrl(&url, 0)), host, port, agent);
|
||||
for (int i = 0; i < headers.n; ++i) {
|
||||
appendf(&request, "%s\r\n", headers.p[i]);
|
||||
}
|
||||
appendf(&request, "\r\n");
|
||||
|
||||
/*
|
||||
* Setup crypto.
|
||||
*/
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_x509_crt *cachain = 0;
|
||||
mbedtls_ctr_drbg_context drbg;
|
||||
if (usessl) {
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ctr_drbg_init(&drbg);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
cachain = GetSslRoots();
|
||||
CHECK_EQ(0, mbedtls_ctr_drbg_seed(&drbg, GetEntropy, 0, "justine", 7));
|
||||
CHECK_EQ(0, mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT));
|
||||
mbedtls_ssl_conf_authmode(&conf, authmode);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, cachain, 0);
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &drbg);
|
||||
if (!IsTiny()) mbedtls_ssl_conf_dbg(&conf, TlsDebug, 0);
|
||||
CHECK_EQ(0, mbedtls_ssl_setup(&ssl, &conf));
|
||||
CHECK_EQ(0, mbedtls_ssl_set_hostname(&ssl, host));
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform DNS lookup.
|
||||
*/
|
||||
struct addrinfo *addr;
|
||||
struct addrinfo hints = {.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
.ai_flags = AI_NUMERICSERV};
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "USAGE: %s URL\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
url = argv[1];
|
||||
CHECK_NE(-1, uriparse(&u, url, strlen(url)), "BAD URL: %`'s", url);
|
||||
CHECK_EQ(kUriSchemeHttp, urischeme(u.scheme, url));
|
||||
urislice2cstr(host, sizeof(host), u.host, url, "127.0.0.1");
|
||||
urislice2cstr(port, sizeof(port), u.port, url, "80");
|
||||
path = uripath(&u);
|
||||
pathstr = path.n ? url + path.i : "/";
|
||||
msg = gc(xstrcat("GET ", pathstr,
|
||||
" HTTP/1.1\r\n"
|
||||
"Host: ",
|
||||
host,
|
||||
"\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"Accept: text/plain; */*\r\n"
|
||||
"Accept-Encoding: identity\r\n"
|
||||
"User-Agent: github.com/jart/cosmopolitan\r\n"
|
||||
"\r\n"));
|
||||
msglen = strlen(msg);
|
||||
CHECK_EQ(EAI_SUCCESS, getaddrinfo(host, port, &hints, &addrs));
|
||||
for (addr = addrs; addr; addr = addr->ai_next) {
|
||||
CHECK_NE(-1, (sock = socket(addr->ai_family, addr->ai_socktype,
|
||||
addr->ai_protocol)));
|
||||
CHECK_NE(-1, connect(sock, addr->ai_addr, addr->ai_addrlen));
|
||||
CHECK_EQ(msglen, write(sock, msg, msglen));
|
||||
shutdown(sock, SHUT_WR);
|
||||
buf[0] = '\0';
|
||||
CHECK_NE(-1, (rc = read(sock, buf, sizeof(buf))));
|
||||
got = rc;
|
||||
CHECK(startswith(buf, "HTTP/1.1 200"), "%`'.*s", got, buf);
|
||||
CHECK_NOTNULL((crlfcrlf = memmem(buf, got, "\r\n\r\n", 4)));
|
||||
need = strtol((char *)firstnonnull(
|
||||
memmem(buf, crlfcrlf - buf, "\r\nContent-Length: ", 18),
|
||||
firstnonnull(memmem(buf, crlfcrlf - buf,
|
||||
"\r\ncontent-length: ", 18),
|
||||
"\r\nContent-Length: -1")) +
|
||||
18,
|
||||
NULL, 10);
|
||||
got = MIN(got - (crlfcrlf + 4 - buf), need);
|
||||
CHECK_EQ(got, write(1, crlfcrlf + 4, got));
|
||||
for (toto = got; toto < need; toto += got) {
|
||||
CHECK_NE(-1, (rc = read(sock, buf, sizeof(buf))));
|
||||
if (!(got = rc)) exit(18);
|
||||
got = MIN(got, need - toto);
|
||||
CHECK_EQ(got, write(1, buf, got));
|
||||
CHECK_EQ(EAI_SUCCESS, getaddrinfo(host, port, &hints, &addr));
|
||||
|
||||
/*
|
||||
* Connect to server.
|
||||
*/
|
||||
int ret, sock;
|
||||
CHECK_NE(-1, (sock = GoodSocket(addr->ai_family, addr->ai_socktype,
|
||||
addr->ai_protocol, false,
|
||||
&(struct timeval){-60})));
|
||||
CHECK_NE(-1, connect(sock, addr->ai_addr, addr->ai_addrlen));
|
||||
freeaddrinfo(addr);
|
||||
if (usessl) {
|
||||
mbedtls_ssl_set_bio(&ssl, &sock, TlsSend, 0, TlsRecv);
|
||||
if ((ret = mbedtls_ssl_handshake(&ssl))) {
|
||||
TlsDie("ssl handshake", ret);
|
||||
}
|
||||
close(sock);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send HTTP Message.
|
||||
*/
|
||||
size_t n;
|
||||
n = appendz(request).i;
|
||||
if (usessl) {
|
||||
ret = mbedtls_ssl_write(&ssl, request, n);
|
||||
if (ret != n) TlsDie("ssl write", ret);
|
||||
} else {
|
||||
CHECK_EQ(n, write(sock, request, n));
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle response.
|
||||
*/
|
||||
int t;
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
struct HttpMessage msg;
|
||||
struct HttpUnchunker u;
|
||||
size_t g, i, hdrlen, paylen;
|
||||
InitHttpMessage(&msg, kHttpResponse);
|
||||
for (p = 0, hdrlen = paylen = t = i = n = 0;;) {
|
||||
if (i == n) {
|
||||
n += 1000;
|
||||
n += n >> 1;
|
||||
p = realloc(p, n);
|
||||
}
|
||||
if (usessl) {
|
||||
if ((rc = mbedtls_ssl_read(&ssl, p + i, n - i)) < 0) {
|
||||
if (rc == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
|
||||
rc = 0;
|
||||
} else {
|
||||
TlsDie("ssl read", rc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CHECK_NE(-1, (rc = read(sock, p + i, n - i)));
|
||||
}
|
||||
g = rc;
|
||||
i += g;
|
||||
switch (t) {
|
||||
case kHttpClientStateHeaders:
|
||||
CHECK(g);
|
||||
CHECK_NE(-1, (rc = ParseHttpMessage(&msg, p, i)));
|
||||
if (rc) {
|
||||
hdrlen = rc;
|
||||
if (100 <= msg.status && msg.status <= 199) {
|
||||
CHECK(!HasHeader(kHttpContentLength) ||
|
||||
HeaderEqualCase(kHttpContentLength, "0"));
|
||||
CHECK(!HasHeader(kHttpTransferEncoding) ||
|
||||
HeaderEqualCase(kHttpTransferEncoding, "identity"));
|
||||
DestroyHttpMessage(&msg);
|
||||
InitHttpMessage(&msg, kHttpResponse);
|
||||
memmove(p, p + hdrlen, i - hdrlen);
|
||||
i -= hdrlen;
|
||||
break;
|
||||
}
|
||||
if (method == kHttpHead) {
|
||||
CHECK_EQ(hdrlen, write(1, p, hdrlen));
|
||||
goto Finished;
|
||||
} else if (msg.status == 204 || msg.status == 304) {
|
||||
goto Finished;
|
||||
}
|
||||
if (HasHeader(kHttpTransferEncoding) &&
|
||||
!HeaderEqualCase(kHttpTransferEncoding, "identity")) {
|
||||
CHECK(HeaderEqualCase(kHttpTransferEncoding, "chunked"));
|
||||
t = kHttpClientStateBodyChunked;
|
||||
memset(&u, 0, sizeof(u));
|
||||
goto Chunked;
|
||||
} else if (HasHeader(kHttpContentLength)) {
|
||||
CHECK_NE(-1, (rc = ParseContentLength(
|
||||
HeaderData(kHttpContentLength),
|
||||
HeaderLength(kHttpContentLength))));
|
||||
t = kHttpClientStateBodyLengthed;
|
||||
paylen = rc;
|
||||
if (paylen > i - hdrlen) {
|
||||
CHECK_EQ(i - hdrlen, write(1, p + hdrlen, i - hdrlen));
|
||||
} else {
|
||||
CHECK_EQ(paylen, write(1, p + hdrlen, paylen));
|
||||
goto Finished;
|
||||
}
|
||||
} else {
|
||||
t = kHttpClientStateBody;
|
||||
CHECK_EQ(i - hdrlen, write(1, p + hdrlen, i - hdrlen));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kHttpClientStateBody:
|
||||
if (!g) goto Finished;
|
||||
CHECK_EQ(g, write(1, p + i - g, g));
|
||||
break;
|
||||
case kHttpClientStateBodyLengthed:
|
||||
CHECK(g);
|
||||
if (i - hdrlen > paylen) g = hdrlen + paylen - (i - g);
|
||||
CHECK_EQ(g, write(1, p + i - g, g));
|
||||
if (i - hdrlen >= paylen) goto Finished;
|
||||
break;
|
||||
case kHttpClientStateBodyChunked:
|
||||
Chunked:
|
||||
CHECK_NE(-1, (rc = Unchunk(&u, p + hdrlen, i - hdrlen, &paylen)));
|
||||
if (rc) {
|
||||
CHECK_EQ(paylen, write(1, p + hdrlen, paylen));
|
||||
goto Finished;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close connection.
|
||||
*/
|
||||
Finished:
|
||||
CHECK_NE(-1, close(sock));
|
||||
|
||||
/*
|
||||
* Free memory.
|
||||
*/
|
||||
free(p);
|
||||
free(headers.p);
|
||||
if (usessl) {
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ctr_drbg_free(&drbg);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
mbedtls_x509_crt_free(cachain);
|
||||
mbedtls_ctr_drbg_free(&drbg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -16,6 +16,6 @@
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
puts(gc(xiso8601ts(NULL)));
|
||||
puts(_gc(xiso8601ts(NULL)));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,376 +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 "dsp/core/core.h"
|
||||
#include "dsp/core/twixt8.h"
|
||||
#include "dsp/scale/scale.h"
|
||||
#include "dsp/tty/itoa8.h"
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/alg/arraylist2.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/winsize.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/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/stb/stb_image.h"
|
||||
|
||||
/**
|
||||
* Hat tips go out to Hornet, CRTC, DESiRE, Hans Petter Jansson, Guihua
|
||||
* Cui, Ming Ronnier Luoand anyone else Mister Rogers would describe as
|
||||
* the The Helpers Of This World who've helped us learn more about the
|
||||
* cool yet exceedingly difficult things possible to do with graphics.
|
||||
*/
|
||||
|
||||
#define DIN99 1
|
||||
#define GAMMA 4.1
|
||||
#define GAMMA_A .05
|
||||
#define GAMMA_B 50.
|
||||
#define GAMMA_C .055
|
||||
#define COLORSPACE_SRC kSrgbD65ToXyzD50
|
||||
#define COLORSPACE_TTY kSrgbD65ToXyzD50
|
||||
|
||||
#define SQR(X) ((X) * (X))
|
||||
#define DEG(X) ((X)*M_PI / 180)
|
||||
|
||||
const double kXyzKappa = 24389 / 27.;
|
||||
const double kXyzEpsilon = 216 / 24389.;
|
||||
|
||||
const double kSrgbD65ToXyzD50[3][3] = {
|
||||
{.4360747, .3850649, .1430804},
|
||||
{.2225045, .7168786, .0606169},
|
||||
{.0139322, .0971045, .7141733},
|
||||
};
|
||||
|
||||
const double kCieRgbEToXyz[3][3] = {
|
||||
{.4887180, .3106803, .2006017},
|
||||
{.1762044, .8129847, .0108109},
|
||||
{.0000000, .0102048, .9897952},
|
||||
};
|
||||
|
||||
const unsigned char kShadePct[] = {0300, 0200, 0100};
|
||||
const unsigned short kShadeRune[] = {u'▓', u'▒', u'░'};
|
||||
|
||||
const unsigned char kAnsiTango[16][3] = {
|
||||
{46, 52, 54}, {204, 0, 0}, {78, 154, 6}, {196, 160, 0},
|
||||
{52, 101, 164}, {117, 80, 123}, {6, 152, 154}, {211, 215, 207},
|
||||
{85, 87, 83}, {239, 41, 41}, {138, 226, 52}, {252, 233, 79},
|
||||
{114, 159, 207}, {173, 127, 168}, {52, 226, 226}, {238, 238, 236},
|
||||
};
|
||||
|
||||
const unsigned char kCga[16][3] = {
|
||||
{0, 0, 0}, {170, 0, 0}, {0, 170, 0}, {170, 85, 0},
|
||||
{0, 0, 170}, {170, 0, 170}, {0, 170, 170}, {170, 170, 170},
|
||||
{85, 85, 85}, {255, 85, 85}, {85, 255, 85}, {255, 255, 85},
|
||||
{85, 85, 255}, {255, 85, 255}, {85, 255, 255}, {255, 255, 255},
|
||||
};
|
||||
|
||||
struct Blends {
|
||||
size_t i, n;
|
||||
struct Blend {
|
||||
unsigned char color[4];
|
||||
unsigned char bg, fg;
|
||||
unsigned short rune;
|
||||
} * p;
|
||||
} blends;
|
||||
|
||||
static double Gamma(double x) {
|
||||
if (x < GAMMA_A) return x / GAMMA_B;
|
||||
return pow(1 / (1 + GAMMA_C) * (x + GAMMA_C), GAMMA);
|
||||
}
|
||||
|
||||
static void *LoadRgb(double rgb[3], const unsigned char pix[3]) {
|
||||
rgb[0] = Gamma(1. / 255 * pix[0]);
|
||||
rgb[1] = Gamma(1. / 255 * pix[1]);
|
||||
rgb[2] = Gamma(1. / 255 * pix[2]);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
static double Lab(double x) {
|
||||
return x > kXyzEpsilon ? cbrtf(x) : (kXyzKappa * x + 16) / 116;
|
||||
}
|
||||
|
||||
static void XyzToLab(double lab[3], const double d50xyz[3]) {
|
||||
double Y, L, a, b;
|
||||
Y = Lab(d50xyz[1]);
|
||||
L = 116 * Y - 16;
|
||||
a = 500 * (Lab(d50xyz[0]) - Y);
|
||||
b = 200 * (Y - Lab(d50xyz[2]));
|
||||
lab[0] = L, lab[1] = a, lab[2] = b;
|
||||
}
|
||||
|
||||
static void XyzToDin99d(unsigned char din99d[3], const double d50xyz[3]) {
|
||||
double e, f, G, C, h, xyz[3], lab[3];
|
||||
memcpy(xyz, d50xyz, sizeof(xyz));
|
||||
xyz[0] = 1.12f * xyz[0] - .12f * xyz[2];
|
||||
XyzToLab(lab, xyz);
|
||||
e = (+lab[1] * cosf(DEG(50)) + lab[2] * sinf(DEG(50)));
|
||||
f = (-lab[1] * sinf(DEG(50)) + lab[2] + cosf(DEG(50))) * 1.14;
|
||||
G = sqrtf(SQR(e) + SQR(f));
|
||||
C = logf(1 + .06 * G) * 22.5f;
|
||||
h = atan2f(f, e) + DEG(50);
|
||||
h = fmodf(h, DEG(360));
|
||||
if (h < 0) h += DEG(360);
|
||||
din99d[0] = MIN(255, MAX(0, 325.22f * logf(1 + .0036 * lab[0]) * 2.5f));
|
||||
din99d[1] = MIN(255, MAX(0, C * cos(h) * 2.5f + 128));
|
||||
din99d[2] = MIN(255, MAX(0, C * sin(h) * 2.5f + 128));
|
||||
}
|
||||
|
||||
static void AddColor(int bg, int fg, int rune, int r, int g, int b, int x) {
|
||||
int i;
|
||||
if (blends.i) {
|
||||
for (i = blends.i; --i;) {
|
||||
if (blends.p[i].color[0] == r && blends.p[i].color[1] == g &&
|
||||
blends.p[i].color[2] == b) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK_NE(
|
||||
-1,
|
||||
APPEND(&blends.p, &blends.i, &blends.n,
|
||||
(&(struct Blend){
|
||||
.bg = bg, .fg = fg, .rune = rune, .color = {r, g, b, x}})));
|
||||
}
|
||||
|
||||
static void AddBlend(int bgxterm, int fgxterm, int rune, int shade,
|
||||
const unsigned char bgrgb[4],
|
||||
const unsigned char fgrgb[4]) {
|
||||
AddColor(bgxterm, fgxterm, rune, twixt8(bgrgb[0], fgrgb[0], shade),
|
||||
twixt8(bgrgb[1], fgrgb[1], shade), twixt8(bgrgb[2], fgrgb[2], shade),
|
||||
0);
|
||||
}
|
||||
|
||||
static void MakeBlends(const unsigned char palette[16][3]) {
|
||||
int r, i, j, k;
|
||||
double rgb[3], xyz[3];
|
||||
unsigned char tab[256][4];
|
||||
unsigned char cube[6] = {0, 0137, 0207, 0257, 0327, 0377};
|
||||
unsigned char seqs[2][2] = {{16, 255}};
|
||||
for (i = 0; i < 16; ++i) {
|
||||
tab[i][0] = palette[i][0];
|
||||
tab[i][1] = palette[i][1];
|
||||
tab[i][2] = palette[i][2];
|
||||
tab[i][3] = i;
|
||||
}
|
||||
for (i = 16; i < 232; ++i) {
|
||||
tab[i][0] = cube[((i - 020) / 044) % 6];
|
||||
tab[i][1] = cube[((i - 020) / 6) % 6];
|
||||
tab[i][2] = cube[(i - 020) % 6];
|
||||
tab[i][3] = i;
|
||||
}
|
||||
for (i = 232; i < 256; ++i) {
|
||||
tab[i][0] = 8 + (i - 232) * 10;
|
||||
tab[i][1] = 8 + (i - 232) * 10;
|
||||
tab[i][2] = 8 + (i - 232) * 10;
|
||||
tab[i][3] = i;
|
||||
}
|
||||
#if DIN99
|
||||
for (i = 0; i < 256; ++i) {
|
||||
LoadRgb(rgb, tab[i]);
|
||||
vmatmul3(xyz, rgb, COLORSPACE_TTY);
|
||||
XyzToDin99d(tab[i], xyz);
|
||||
}
|
||||
#endif
|
||||
for (r = 0; r < ARRAYLEN(seqs); ++r) {
|
||||
for (i = seqs[r][0]; i <= seqs[r][1]; ++i) {
|
||||
for (j = seqs[r][0]; j <= seqs[r][1]; ++j) {
|
||||
if (i == j) {
|
||||
AddColor(i, 0, 0, tab[i][0], tab[i][1], tab[i][2], 0);
|
||||
} else {
|
||||
for (k = 0; k < ARRAYLEN(kShadeRune); ++k) {
|
||||
AddBlend(i, j, kShadeRune[k], kShadePct[k], tab[i], tab[j]);
|
||||
AddBlend(j, i, kShadeRune[k], kShadePct[k], tab[j], tab[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int PickColor(unsigned char color[3]) {
|
||||
int i, best, least, dist;
|
||||
best = -1;
|
||||
least = INT_MAX;
|
||||
for (i = 0; i < blends.i; ++i) {
|
||||
dist = SQR(blends.p[i].color[0] - color[0]) +
|
||||
SQR(blends.p[i].color[1] - color[1]) +
|
||||
SQR(blends.p[i].color[2] - color[2]);
|
||||
if (dist < least) {
|
||||
least = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
static void SetBg(int x) {
|
||||
if (0 <= x && x < 16) {
|
||||
if (x < 8) {
|
||||
x += 40;
|
||||
} else {
|
||||
x -= 8;
|
||||
x *= 100;
|
||||
}
|
||||
printf("\e[%dm", x);
|
||||
} else {
|
||||
/* assert(false); */
|
||||
printf("\e[48;5;%dm", x);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetFg(int x) {
|
||||
if (0 <= x && x < 16) {
|
||||
if (x < 8) {
|
||||
x += 30;
|
||||
} else {
|
||||
x -= 8;
|
||||
x *= 90;
|
||||
}
|
||||
printf("\e[%dm", x);
|
||||
} else {
|
||||
/* assert(false); */
|
||||
printf("\e[38;5;%dm", x);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintImage(long yn, long xn, unsigned char src[4][yn][xn]) {
|
||||
int y, x, c;
|
||||
double rgb[3], xyz[3];
|
||||
unsigned char din99d[3];
|
||||
for (y = 0; y < yn; ++y) {
|
||||
printf("\n");
|
||||
for (x = 0; x < xn; ++x) {
|
||||
din99d[0] = src[0][y][x];
|
||||
din99d[1] = src[1][y][x];
|
||||
din99d[2] = src[2][y][x];
|
||||
#if DIN99
|
||||
LoadRgb(rgb, din99d);
|
||||
vmatmul3(xyz, rgb, COLORSPACE_SRC);
|
||||
XyzToDin99d(din99d, xyz);
|
||||
#endif
|
||||
c = PickColor(din99d);
|
||||
if (blends.p[c].rune) {
|
||||
SetBg(blends.p[c].bg);
|
||||
SetFg(blends.p[c].fg);
|
||||
printf("%hc", blends.p[c].rune);
|
||||
} else {
|
||||
SetBg(blends.p[c].bg);
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\e[0m");
|
||||
}
|
||||
printf("\r");
|
||||
}
|
||||
|
||||
static void *Deinterlace(long dcn, long dyn, long dxn,
|
||||
unsigned char dst[dcn][dyn][dxn], long syw, long sxw,
|
||||
long scw, const unsigned char src[syw][sxw][scw],
|
||||
long syn, long sxn, long sy0, long sx0, long sc0) {
|
||||
long y, x, c;
|
||||
for (y = 0; y < dyn; ++y) {
|
||||
for (x = 0; x < dxn; ++x) {
|
||||
for (c = 0; c < dcn; ++c) {
|
||||
dst[c][y][x] = src[sy0 + y][sx0 + x][sc0 + c];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void GetTermSize(int out_rows[1], int out_cols[1]) {
|
||||
struct winsize ws;
|
||||
ws.ws_row = 24;
|
||||
ws.ws_col = 80;
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) {
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
|
||||
}
|
||||
out_rows[0] = ws.ws_row;
|
||||
out_cols[0] = ws.ws_col;
|
||||
}
|
||||
|
||||
static void ProcessImage(long syn, long sxn, unsigned char img[syn][sxn][4]) {
|
||||
int dyn, dxn;
|
||||
double ry, rx;
|
||||
GetTermSize(&dyn, &dxn);
|
||||
ry = syn, rx = sxn;
|
||||
ry /= dyn, rx /= dxn;
|
||||
PrintImage(
|
||||
dyn, dxn,
|
||||
EzGyarados(4, dyn, dxn, gc(xmemalign(32, dyn * dxn * 4)), 4, syn, sxn,
|
||||
Deinterlace(4, syn, sxn, gc(xmemalign(32, syn * sxn * 4)), syn,
|
||||
sxn, 4, img, syn, sxn, 0, 0, 0),
|
||||
0, 4, dyn, dxn, syn, sxn, ry, rx, 0, 0));
|
||||
}
|
||||
|
||||
static void WithImageFile(const char *path,
|
||||
void fn(long yn, long xn,
|
||||
unsigned char src[yn][xn][4])) {
|
||||
struct stat st;
|
||||
void *map, *data;
|
||||
int fd, yn, xn, cn;
|
||||
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
CHECK_GT(st.st_size, 0);
|
||||
CHECK_LE(st.st_size, INT_MAX);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
|
||||
CHECK_NOTNULL(
|
||||
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s",
|
||||
path);
|
||||
CHECK_NE(-1, munmap(map, st.st_size));
|
||||
CHECK_NE(-1, close(fd));
|
||||
fn(yn, xn, data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void PrintData(void) {
|
||||
int i;
|
||||
for (i = 0; i < blends.i; ++i) {
|
||||
printf("%3d %3d %3d %3d %3d %d\n", blends.p[i].color[0],
|
||||
blends.p[i].color[1], blends.p[i].color[2], blends.p[i].bg,
|
||||
blends.p[i].fg, blends.p[i].rune);
|
||||
}
|
||||
}
|
||||
|
||||
void *OpenRgbMap(const char *path) {
|
||||
int fd;
|
||||
void *map;
|
||||
size_t size;
|
||||
size = 256 * 256 * 256 * 3;
|
||||
CHECK_NE(-1, (fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644)));
|
||||
CHECK_NE(-1, ftruncate(fd, size));
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)));
|
||||
CHECK_NE(-1, close(fd));
|
||||
return map;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
MakeBlends(kCga);
|
||||
for (i = 1; i < argc; ++i) {
|
||||
WithImageFile(argv[i], ProcessImage);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,44 +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/fmt/itoa.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/e820.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
const char *DescribeMemoryType(int type) {
|
||||
switch (type) {
|
||||
case kMemoryUsable:
|
||||
return "kMemoryUsable";
|
||||
case kMemoryUnusable:
|
||||
return "kMemoryUnusable";
|
||||
case kMemoryAcpiReclaimable:
|
||||
return "kMemoryAcpiReclaimable";
|
||||
case kMemoryAcpiNvs:
|
||||
return "kMemoryAcpiNvs";
|
||||
case kMemoryBad:
|
||||
return "kMemoryBad";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
const char *ts;
|
||||
struct mman *mm;
|
||||
mm = (struct mman *)(BANE + 0x0500);
|
||||
for (i = 0; i < mm->e820n; ++i) {
|
||||
printf("%p-%p %s\n", mm->e820[i].addr, mm->e820[i].size,
|
||||
DescribeMemoryType(mm->e820[i].type));
|
||||
}
|
||||
for (;;) asm("pause");
|
||||
return 0;
|
||||
}
|
||||
@@ -45,6 +45,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_USER32 \
|
||||
@@ -65,14 +66,19 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
NET_HTTP \
|
||||
NET_HTTPS \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_QUICKJS \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_LUA \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_STB \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_ZLIB \
|
||||
TOOL_BUILD_LIB \
|
||||
TOOL_VIZ_LIB
|
||||
|
||||
EXAMPLES_DEPS := \
|
||||
@@ -80,7 +86,6 @@ EXAMPLES_DEPS := \
|
||||
|
||||
o/$(MODE)/examples/examples.pkg: \
|
||||
$(EXAMPLES_OBJS) \
|
||||
$(THIRD_PARTY_DUKTAPE_A).pkg \
|
||||
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/examples/unbourne.o: \
|
||||
@@ -95,11 +100,10 @@ o/$(MODE)/examples/%.com.dbg: \
|
||||
$(APE)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/hellojs.com.dbg: \
|
||||
o/$(MODE)/examples/hellolua.com.dbg: \
|
||||
$(EXAMPLES_DEPS) \
|
||||
$(THIRD_PARTY_DUKTAPE) \
|
||||
o/$(MODE)/examples/hellojs.o \
|
||||
o/$(MODE)/examples/hello.js.zip.o \
|
||||
o/$(MODE)/examples/hellolua.o \
|
||||
o/$(MODE)/examples/hellolua.lua.zip.o \
|
||||
o/$(MODE)/examples/examples.pkg \
|
||||
$(CRT) \
|
||||
$(APE)
|
||||
@@ -116,7 +120,6 @@ o/$(MODE)/examples/ispell.com.dbg: \
|
||||
|
||||
o/$(MODE)/examples/nesemu1.com.dbg: \
|
||||
$(EXAMPLES_DEPS) \
|
||||
$(THIRD_PARTY_DUKTAPE) \
|
||||
o/$(MODE)/examples/nesemu1.o \
|
||||
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
|
||||
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
|
||||
|
||||
@@ -1,17 +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/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) return 1;
|
||||
execv(argv[1], argv + 1);
|
||||
abort();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#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/macros.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Fast Division Using Multiplication Tutorial
|
||||
*
|
||||
* Expected program output:
|
||||
*
|
||||
* 23 / 3 = 7
|
||||
* 0x5555555555555556 1 1
|
||||
* division l: 16𝑐 5𝑛𝑠
|
||||
* fast div l: 5𝑐 2𝑛𝑠
|
||||
* precomps l: 70𝑐 23𝑛𝑠
|
||||
*/
|
||||
|
||||
struct Divisor {
|
||||
uint64_t m;
|
||||
uint8_t s;
|
||||
uint8_t t;
|
||||
};
|
||||
|
||||
struct Divisor GetDivisor(uint64_t d) {
|
||||
int b;
|
||||
uint128_t x;
|
||||
if (!d) raise(SIGFPE);
|
||||
b = __builtin_clzll(d) ^ 63;
|
||||
x = -d & (((1ull << b) - 1) | (1ull << b));
|
||||
return (struct Divisor){(x << 64) / d + 1, MIN(1, b + 1), MAX(0, b)};
|
||||
}
|
||||
|
||||
uint64_t Divide(uint64_t x, struct Divisor d) {
|
||||
uint128_t t;
|
||||
uint64_t l, h;
|
||||
t = d.m;
|
||||
t *= x;
|
||||
l = t;
|
||||
h = t >> 64;
|
||||
l = (x - h) >> d.s;
|
||||
return (h + l) >> d.t;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("23 / 3 = %ld\n", Divide(23, GetDivisor(3)));
|
||||
volatile struct Divisor v = GetDivisor(3);
|
||||
volatile uint64_t x = 23, y = 3, z;
|
||||
EZBENCH2("division", donothing, z = x / y);
|
||||
EZBENCH2("fast div", donothing, z = Divide(x, v));
|
||||
EZBENCH2("precomp ", donothing, v = GetDivisor(y));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#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/stdio/stdio.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Fast Modulus Using Multiplication Tutorial
|
||||
*
|
||||
* Expected program output:
|
||||
*
|
||||
* 23 / 3 = 7
|
||||
* 0x5555555555555556 1 1
|
||||
* modulus l: 15𝑐 5𝑛𝑠
|
||||
* fastmod l: 4𝑐 1𝑛𝑠
|
||||
* precomp l: 18𝑐 6𝑛𝑠
|
||||
*/
|
||||
|
||||
struct Modulus {
|
||||
uint64_t c;
|
||||
uint64_t d;
|
||||
};
|
||||
|
||||
struct Modulus GetModulus(uint64_t d) {
|
||||
return (struct Modulus){0xFFFFFFFFFFFFFFFFull / d + 1, d};
|
||||
}
|
||||
|
||||
uint64_t Modulus(uint64_t x, struct Modulus m) {
|
||||
return ((uint128_t)(m.c * x) * m.d) >> 64;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("%#lx %% %d = %d\n", 0x23, 3, Modulus(23, GetModulus(3)));
|
||||
printf("%#lx %% %d = %d\n", 0x123, 17, Modulus(0x123, GetModulus(17)));
|
||||
volatile struct Modulus v = GetModulus(3);
|
||||
volatile uint64_t x = 23, y = 3, z;
|
||||
EZBENCH2("modulus", donothing, z = x % y);
|
||||
EZBENCH2("fastmod", donothing, z = Modulus(x, v));
|
||||
EZBENCH2("precomp", donothing, v = GetModulus(y));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,66 +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/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static const struct itimerval kTimer = {{0, 10000}, {0, 10000}}; /* 10ms */
|
||||
static volatile bool32 showprogress_;
|
||||
static const char *magic_;
|
||||
|
||||
void OnInterrupt(int sig) {
|
||||
showprogress_ = true;
|
||||
}
|
||||
|
||||
void ShowProgress(uintmax_t i, uintmax_t j, uintmax_t n) {
|
||||
fprintf(stderr, "%s%,40jd%,40jd%,40jd\r\n", magic_, i, j, n);
|
||||
showprogress_ = false;
|
||||
}
|
||||
|
||||
static bool IsPrime(uintmax_t i) {
|
||||
uintmax_t j, n;
|
||||
for (j = 3, n = (unsigned long)floorl(sqrtl(i)); j <= n; j += 2) {
|
||||
if (showprogress_) ShowProgress(i, j, n);
|
||||
if (i % j == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TryNumber(uintmax_t x, uintmax_t i) {
|
||||
if (IsPrime(i)) {
|
||||
printf("%s%,jd%s%,jd\n", "the prime nearest ", x, " is ", i);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uintmax_t x, i, j;
|
||||
CHECK_EQ(2, argc);
|
||||
signal(SIGALRM, OnInterrupt);
|
||||
setitimer(ITIMER_REAL, &kTimer, NULL);
|
||||
magic_ = cancolor() ? "\e[F\e[K" : "";
|
||||
if ((x = strtoumax(argv[1], NULL, 0)) % 2 == 0) ++x;
|
||||
TryNumber(x, x);
|
||||
for (i = x, j = x;;) {
|
||||
if (i < UINTMAX_MAX) TryNumber(x, i), i += 2;
|
||||
if (j > 1) TryNumber(x, j), j -= 2;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +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/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid;
|
||||
pid = fork();
|
||||
fprintf(stderr, "fork returned %d\n", pid);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#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/fmt/itoa.h"
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int c, n;
|
||||
char a[22];
|
||||
if ((c = GetCpuCount())) {
|
||||
n = int64toarray_radix10(c, a);
|
||||
a[n++] = '\n';
|
||||
return write(1, a, n) == n ? 0 : 1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
#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/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/grnd.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
#define B 4096
|
||||
|
||||
bool isdone;
|
||||
bool isbinary;
|
||||
unsigned long count = -1;
|
||||
|
||||
uint64_t bcast(uint64_t f(void)) {
|
||||
unsigned i;
|
||||
uint64_t x;
|
||||
for (x = i = 0; i < 8; ++i) {
|
||||
x <<= 8;
|
||||
x |= f() & 255;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t randv6(void) {
|
||||
static int16_t gorp;
|
||||
gorp = (gorp + 625) & 077777;
|
||||
return gorp;
|
||||
}
|
||||
|
||||
uint64_t randv7(void) {
|
||||
static uint32_t randx = 1;
|
||||
return ((randx = randx * 1103515245 + 12345) >> 16) & 077777;
|
||||
}
|
||||
|
||||
uint64_t zero(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t inc(void) {
|
||||
static uint64_t x;
|
||||
return x++;
|
||||
}
|
||||
|
||||
uint64_t unixv6(void) {
|
||||
return bcast(randv6);
|
||||
}
|
||||
|
||||
uint64_t unixv7(void) {
|
||||
return bcast(randv7);
|
||||
}
|
||||
|
||||
uint64_t ape(void) {
|
||||
static int i;
|
||||
if ((i += 8) > _end - _base) i = 8;
|
||||
return READ64LE(_base + i);
|
||||
}
|
||||
|
||||
uint64_t moby(void) {
|
||||
static int i;
|
||||
if ((i += 8) > kMobySize) i = 8;
|
||||
return READ64LE(kMoby + i);
|
||||
}
|
||||
|
||||
uint64_t knuth(void) {
|
||||
uint64_t a, b;
|
||||
static uint64_t x = 1;
|
||||
x *= 6364136223846793005;
|
||||
x += 1442695040888963407;
|
||||
a = x >> 32;
|
||||
x *= 6364136223846793005;
|
||||
x += 1442695040888963407;
|
||||
b = x >> 32;
|
||||
return a | b << 32;
|
||||
}
|
||||
|
||||
uint64_t vigna(void) {
|
||||
static uint64_t x;
|
||||
uint64_t z = (x += 0x9e3779b97f4a7c15);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
uint64_t rngset64(void) {
|
||||
static unsigned i;
|
||||
static uint64_t s;
|
||||
if (!i) {
|
||||
s = rand64();
|
||||
i = (s + 1) & (511);
|
||||
}
|
||||
return MarsagliaXorshift64(&s);
|
||||
}
|
||||
|
||||
uint64_t xorshift64(void) {
|
||||
static uint64_t s = kMarsagliaXorshift64Seed;
|
||||
return MarsagliaXorshift64(&s);
|
||||
}
|
||||
|
||||
uint64_t xorshift32(void) {
|
||||
static uint32_t s = kMarsagliaXorshift32Seed;
|
||||
uint64_t a = MarsagliaXorshift32(&s);
|
||||
uint64_t b = MarsagliaXorshift32(&s);
|
||||
return (uint64_t)a << 32 | b;
|
||||
}
|
||||
|
||||
uint64_t libc(void) {
|
||||
uint64_t x;
|
||||
CHECK_EQ(8, getrandom(&x, 8, 0));
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t kernel(void) {
|
||||
uint64_t x;
|
||||
CHECK_EQ(8, getrandom(&x, 8, GRND_NORDRND));
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t hardware(void) {
|
||||
uint64_t x;
|
||||
CHECK_EQ(8, getrandom(&x, 8, GRND_NOSYSTEM));
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t rdrnd(void) {
|
||||
char cf;
|
||||
int i = 0;
|
||||
uint64_t x;
|
||||
CHECK(X86_HAVE(RDRND));
|
||||
for (;;) {
|
||||
asm volatile(CFLAG_ASM("rdrand\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return x;
|
||||
if (++i < 10) continue;
|
||||
asm volatile("pause");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t rdseed(void) {
|
||||
char cf;
|
||||
int i = 0;
|
||||
uint64_t x;
|
||||
CHECK(X86_HAVE(RDSEED));
|
||||
for (;;) {
|
||||
asm volatile(CFLAG_ASM("rdseed\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return x;
|
||||
if (++i < 10) continue;
|
||||
asm volatile("pause");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct Function {
|
||||
const char *s;
|
||||
uint64_t (*f)(void);
|
||||
} kFunctions[] = {
|
||||
{"ape", ape}, //
|
||||
{"hardware", hardware}, //
|
||||
{"inc", inc}, //
|
||||
{"kernel", kernel}, //
|
||||
{"knuth", knuth}, //
|
||||
{"libc", libc}, //
|
||||
{"moby", moby}, //
|
||||
{"rand64", rand64}, //
|
||||
{"rdrand", rdrnd}, //
|
||||
{"rdrnd", rdrnd}, //
|
||||
{"rdseed", rdseed}, //
|
||||
{"rngset64", rngset64}, //
|
||||
{"unixv6", unixv6}, //
|
||||
{"unixv7", unixv7}, //
|
||||
{"vigna", vigna}, //
|
||||
{"xorshift32", xorshift32}, //
|
||||
{"xorshift64", xorshift64}, //
|
||||
{"zero", zero}, //
|
||||
};
|
||||
|
||||
void OnInt(int sig) {
|
||||
isdone = true;
|
||||
}
|
||||
|
||||
wontreturn void PrintUsage(FILE *f, int rc) {
|
||||
fprintf(f, "Usage: %s [-b] [-n NUM] [FUNC]\n", program_invocation_name);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *p;
|
||||
int i, opt;
|
||||
ssize_t rc;
|
||||
uint64_t x;
|
||||
static char buf[B];
|
||||
uint64_t (*f)(void);
|
||||
|
||||
while ((opt = getopt(argc, argv, "hbc:n:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
isbinary = true;
|
||||
break;
|
||||
case 'c':
|
||||
case 'n':
|
||||
count = strtoul(optarg, 0, 0);
|
||||
break;
|
||||
case 'h':
|
||||
PrintUsage(stdout, EXIT_SUCCESS);
|
||||
default:
|
||||
PrintUsage(stderr, EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
f = libc;
|
||||
} else {
|
||||
for (f = 0, i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
||||
if (!strcasecmp(argv[optind], kFunctions[i].s)) {
|
||||
f = kFunctions[i].f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!f) {
|
||||
fprintf(stderr, "unknown function: %`'s\n", argv[optind]);
|
||||
fprintf(stderr, "try: ");
|
||||
for (i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
||||
if (i) fprintf(stderr, ", ");
|
||||
fprintf(stderr, "%s", kFunctions[i].s);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
signal(SIGINT, OnInt);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!isbinary) {
|
||||
for (; count && !isdone && !feof(stdout); --count) {
|
||||
printf("0x%016lx\n", f());
|
||||
}
|
||||
fflush(stdout);
|
||||
return ferror(stdout) ? 1 : 0;
|
||||
}
|
||||
|
||||
while (count && !isdone) {
|
||||
if (count >= B) {
|
||||
for (i = 0; i < B / 8; ++i) {
|
||||
x = f();
|
||||
p = buf + i * 8;
|
||||
WRITE64LE(p, x);
|
||||
}
|
||||
for (i = 0; i < B; i += rc) {
|
||||
rc = write(1, buf + i, B - i);
|
||||
if (rc == -1 && errno == EPIPE) exit(1);
|
||||
if (rc == -1) perror("write"), exit(1);
|
||||
}
|
||||
} else {
|
||||
x = f();
|
||||
rc = write(1, &x, MIN(8, count));
|
||||
}
|
||||
if (!rc) break;
|
||||
if (rc == -1 && errno == EPIPE) exit(1);
|
||||
if (rc == -1) perror("write"), exit(1);
|
||||
count -= rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+65
-1
@@ -7,9 +7,73 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/enum/cw.h"
|
||||
#include "libc/nt/enum/mb.h"
|
||||
#include "libc/nt/enum/sw.h"
|
||||
#include "libc/nt/enum/wm.h"
|
||||
#include "libc/nt/enum/ws.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/messagebox.h"
|
||||
#include "libc/nt/struct/msg.h"
|
||||
#include "libc/nt/struct/wndclass.h"
|
||||
#include "libc/nt/windows.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* @fileoverview GUI Example
|
||||
*
|
||||
* Cosmopolitan has had a razor sharp focus on making sockets and stdio
|
||||
* work well across platforms. When you call a function like read(), it
|
||||
* will just work on platforms like Windows too. In order to do that we
|
||||
* need to support the WIN32 API, which you can use, but please note it
|
||||
* isn't polyfilled on other platforms in the same way as POSIX APIs.
|
||||
*/
|
||||
|
||||
static const char16_t kClassName[] = u"cosmopolitan";
|
||||
|
||||
static int64_t WindowProc(int64_t hwnd, uint32_t uMsg, uint64_t wParam,
|
||||
int64_t lParam) {
|
||||
switch (uMsg) {
|
||||
case kNtWmDestroy:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
default:
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
static void Gui(void) {
|
||||
int64_t h;
|
||||
struct NtMsg msg;
|
||||
struct NtWndClass wc;
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.lpfnWndProc = NT2SYSV(WindowProc);
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpszClassName = kClassName;
|
||||
RegisterClass(&wc);
|
||||
h = CreateWindowEx(0, kClassName, u"Hello Cosmopolitan",
|
||||
kNtWsOverlappedwindow, kNtCwUsedefault, kNtCwUsedefault,
|
||||
kNtCwUsedefault, kNtCwUsedefault, 0, 0, wc.hInstance, 0);
|
||||
ShowWindow(h, kNtSwNormal);
|
||||
/*
|
||||
* NOTE: Cosmopolitan linker script is hard-coded to change the
|
||||
* subsystem from CUI to GUI when GetMessage() is linked.
|
||||
*/
|
||||
while (GetMessage(&msg, 0, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return MessageBox(0, u"hello world", u"cosmopolitan", kNtMbOk) ? 0 : 1;
|
||||
if (!IsWindows()) {
|
||||
fputs("Sorry! This GUI demo only runs on Windows\n", stderr);
|
||||
fputs("https://github.com/jart/cosmopolitan/issues/57\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
Gui();
|
||||
}
|
||||
@@ -10,13 +10,6 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main() {
|
||||
/*
|
||||
* Cosmopolitan's "Hello World" demonstrates a best practice.
|
||||
*
|
||||
* Since we conditionally link heavyweight features based on which
|
||||
* characters are present in the format string, it's a good idea to
|
||||
* have that string consist solely of directives.
|
||||
*/
|
||||
printf("%s\n", "hello world");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
console.log('Hello world!\n');
|
||||
console.log('2+3=' + NativeAdd(2, 3) + '\n');
|
||||
+3
-5
@@ -8,12 +8,10 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main() {
|
||||
dprintf(STDOUT_FILENO, "%s\n", gc(xasprintf("%'s", "(╯°□°)╯︵' ┻━┻")));
|
||||
printf("%`'s\n", "hello\1\2world→→");
|
||||
return errno;
|
||||
}
|
||||
@@ -1,16 +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/errno.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main() {
|
||||
printf("%s \n", "hello world");
|
||||
return errno;
|
||||
}
|
||||
@@ -1,70 +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/stat.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "third_party/duktape/duktape.h"
|
||||
|
||||
STATIC_YOINK("zip_uri_support");
|
||||
|
||||
static duk_ret_t NativePrint(duk_context *ctx) {
|
||||
duk_push_string(ctx, " ");
|
||||
duk_insert(ctx, 0);
|
||||
duk_join(ctx, duk_get_top(ctx) - 1);
|
||||
fputs(duk_safe_to_string(ctx, -1), stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static duk_ret_t NativeAdd(duk_context *ctx) {
|
||||
int i, n;
|
||||
double r;
|
||||
n = duk_get_top(ctx);
|
||||
for (r = i = 0; i < n; i++) r += duk_to_number(ctx, i);
|
||||
duk_push_number(ctx, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int fd;
|
||||
struct stat st;
|
||||
const char *code;
|
||||
duk_context *ctx;
|
||||
showcrashreports();
|
||||
ctx = duk_create_heap_default();
|
||||
|
||||
/* define NativeAdd() */
|
||||
duk_push_c_function(ctx, NativeAdd, DUK_VARARGS);
|
||||
duk_put_global_string(ctx, "NativeAdd");
|
||||
|
||||
/* define console.log() */
|
||||
duk_push_global_object(ctx);
|
||||
duk_push_c_function(ctx, NativePrint, DUK_VARARGS);
|
||||
duk_push_string(ctx, "name");
|
||||
duk_push_string(ctx, "log");
|
||||
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);
|
||||
duk_set_magic(ctx, -1, 0);
|
||||
duk_put_prop_string(ctx, -2, "log");
|
||||
duk_put_global_string(ctx, "console");
|
||||
|
||||
CHECK_NE(-1, (fd = open("zip:examples/hello.js", O_RDONLY)));
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
CHECK_NOTNULL((code = gc(calloc(1, st.st_size + 1))));
|
||||
CHECK_EQ(st.st_size, read(fd, code, st.st_size));
|
||||
CHECK_NE(-1, close(fd));
|
||||
|
||||
duk_eval_string(ctx, code);
|
||||
duk_pop(ctx);
|
||||
duk_destroy_heap(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#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 "third_party/lua/lauxlib.h"
|
||||
#include "third_party/lua/lualib.h"
|
||||
|
||||
int NativeAdd(lua_State *L) {
|
||||
lua_Number x, y;
|
||||
x = luaL_checknumber(L, 1);
|
||||
y = luaL_checknumber(L, 2);
|
||||
lua_pushnumber(L, x + y);
|
||||
return 1; /* number of results */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
lua_State *L;
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
lua_pushcfunction(L, NativeAdd);
|
||||
lua_setglobal(L, "NativeAdd");
|
||||
luaL_dofile(L, "zip:examples/hellolua.lua");
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
print(string.format("2 + 3 = %g", NativeAdd(2, 3)))
|
||||
@@ -0,0 +1,43 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#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"
|
||||
|
||||
const struct itimerval kHertz = {
|
||||
{1, 0},
|
||||
{0, 1},
|
||||
};
|
||||
|
||||
bool hertz;
|
||||
|
||||
void OnAlrm(void) {
|
||||
hertz = true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CHECK_NE(-1, xsigaction(SIGALRM, OnAlrm, 0, 0, 0));
|
||||
CHECK_NE(-1, setitimer(ITIMER_REAL, &kHertz, NULL));
|
||||
for (;;) {
|
||||
CHECK_EQ(-1, pause());
|
||||
CHECK_EQ(EINTR, errno);
|
||||
if (hertz) {
|
||||
hertz = false;
|
||||
printf("ding\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#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/stdio/stdio.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/stb/stb_image.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Utility for printing HTML <img> tags.
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void *p;
|
||||
size_t n;
|
||||
int yn, xn, cn;
|
||||
if (argc != 2) return 1;
|
||||
if (!(p = xslurp(argv[1], &n))) return 2;
|
||||
if (!(p = stbi_load_from_memory(p, n, &xn, &yn, &cn, 0))) return 3;
|
||||
printf("<img src=\"%s\" width=\"%d\" height=\"%d\"\n"
|
||||
" alt=\"[%s]\">\n",
|
||||
argv[1], (xn + 1) >> 1, (yn + 1) >> 1, argv[1]);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,80 +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/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Measure CPU clock mystery constants.
|
||||
* @note CPUID EAX=15h/16h is a joke
|
||||
*/
|
||||
|
||||
const long double kInterval = 0.001L;
|
||||
|
||||
long double start_;
|
||||
char dtoabuf_[3][32];
|
||||
volatile bool isdone_;
|
||||
|
||||
void OnCtrlC(int sig) {
|
||||
isdone_ = true;
|
||||
}
|
||||
|
||||
long double now(void) {
|
||||
return dtime(CLOCK_MONOTONIC);
|
||||
}
|
||||
|
||||
long double GetSample(void) {
|
||||
uint64_t tick1, tick2;
|
||||
long double time1, time2;
|
||||
time1 = now();
|
||||
tick1 = rdtsc();
|
||||
nanosleep(&(struct timespec){0, 100000}, NULL);
|
||||
time2 = now();
|
||||
tick2 = rdtsc();
|
||||
return ((time2 - time1) * 1e9L) / (long double)(tick2 - tick1);
|
||||
}
|
||||
|
||||
void MeasureNanosecondsPerAlwaysRunningTimerCycle(void) {
|
||||
int i;
|
||||
long double avg, samp, elapsed;
|
||||
start_ = now();
|
||||
for (i = 1, avg = 1.0L; !isdone_; ++i) {
|
||||
samp = GetSample();
|
||||
avg += (samp - avg) / i;
|
||||
dsleep(kInterval);
|
||||
elapsed = now() - start_;
|
||||
g_xfmt_p(dtoabuf_[0], &avg, 15, 32, 0);
|
||||
g_xfmt_p(dtoabuf_[1], &samp, 15, 32, 0);
|
||||
g_xfmt_p(dtoabuf_[2], &elapsed, 15, 32, 0);
|
||||
printf("1c = %sns (last=%sns spent=%ss)\n", dtoabuf_[0], dtoabuf_[1],
|
||||
dtoabuf_[2]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!X86_HAVE(INVTSC)) {
|
||||
fprintf(stderr, "warning: html can reprogram your microcode\n");
|
||||
}
|
||||
if (X86_HAVE(HYPERVISOR)) {
|
||||
fprintf(stderr, "warning: virtual machine rdtsc isn't great\n");
|
||||
}
|
||||
CHECK_NE(-1, xsigaction(SIGINT, OnCtrlC, 0, 0, NULL));
|
||||
MeasureNanosecondsPerAlwaysRunningTimerCycle();
|
||||
return 0;
|
||||
}
|
||||
@@ -267,8 +267,12 @@ int editorReadKey(int64_t fd) {
|
||||
if (read(fd, seq + 2, 1) == 0) return CTRL('[');
|
||||
if (seq[2] == '~') {
|
||||
switch (seq[1]) {
|
||||
case '1':
|
||||
return HOME_KEY;
|
||||
case '3':
|
||||
return DEL_KEY;
|
||||
case '4':
|
||||
return END_KEY;
|
||||
case '5':
|
||||
return PAGE_UP;
|
||||
case '6':
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ void List(const char *path) {
|
||||
if (strcmp(path, ".") == 0) {
|
||||
vpath = "";
|
||||
} else if (!endswith(path, "/")) {
|
||||
vpath = gc(xasprintf("%s/", path));
|
||||
vpath = _gc(xasprintf("%s/", path));
|
||||
} else {
|
||||
vpath = path;
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ void WalkPaths(const char *dirpath) {
|
||||
if (strcmp(e->d_name, "o") == 0) continue;
|
||||
if (strcmp(e->d_name, ".git") == 0) continue;
|
||||
if (e->d_type == DT_DIR) {
|
||||
WalkPaths(gc(path));
|
||||
WalkPaths(_gc(path));
|
||||
} else {
|
||||
CHECK_NE(-1, lstat(path, &st), "%s", path);
|
||||
f.mt = st.st_mtim;
|
||||
|
||||
@@ -1,19 +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/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *s = malloc(1024 * 1024 * 2 + argc);
|
||||
strcpy(s, "hello");
|
||||
puts(s);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,50 +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/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/*
|
||||
OpenBSD
|
||||
00025ff61000 000000000000 65536
|
||||
00026cf1d000 00000cfbc000 65536
|
||||
000254d83000 ffffe7e66000 65536
|
||||
0002c7bde000 000072e5b000 65536
|
||||
000253ff9000 ffff8c41b000 65536
|
||||
0002e96f3000 0000956fa000 65536
|
||||
000236346000 ffff4cc53000 65536
|
||||
0002ce744000 0000983fe000 65536
|
||||
0002fe0b8000 00002f974000 65536
|
||||
000225cd7000 ffff27c1f000 65536
|
||||
*/
|
||||
|
||||
struct Mapping {
|
||||
uint8_t *map;
|
||||
size_t mapsize;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
size_t i;
|
||||
struct Mapping m[10];
|
||||
for (i = 0; i < ARRAYLEN(m); ++i) {
|
||||
m[i].mapsize = FRAMESIZE;
|
||||
m[i].map = mmap(NULL, m[i].mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(m); ++i) {
|
||||
printf("%p %p %zu\n", m[i].map, i ? m[i].map - m[i - 1].map : 0,
|
||||
m[i].mapsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
#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/dns/dns.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
/**
|
||||
* @fileoverview netcat clone
|
||||
*
|
||||
* Implemented because BusyBox's netcat doesn't detect remote close and
|
||||
* lingers in the CLOSE_WAIT wait possibly due to file descriptor leaks
|
||||
*
|
||||
* Here's an example usage:
|
||||
*
|
||||
* make -j8 o//examples/nc.com
|
||||
* printf 'GET /\r\n\r\n' | o//examples/nc.com justine.lol 80
|
||||
*
|
||||
* Once upon time we called this command "telnet"
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ssize_t rc;
|
||||
size_t i, got;
|
||||
char buf[1500];
|
||||
bool halfclose = true;
|
||||
const char *host, *port;
|
||||
int opt, err, toto, sock;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct linger linger = {true, 1};
|
||||
struct pollfd fds[2] = {{-1, POLLIN}, {-1, POLLIN}};
|
||||
struct addrinfo hint = {AI_NUMERICSERV, AF_INET, SOCK_STREAM, IPPROTO_TCP};
|
||||
|
||||
while ((opt = getopt(argc, argv, "hH")) != -1) {
|
||||
switch (opt) {
|
||||
case 'H':
|
||||
halfclose = false;
|
||||
break;
|
||||
case 'h':
|
||||
fputs("Usage: ", stdout);
|
||||
fputs(argv[0], stdout);
|
||||
fputs(" [-hH] IP PORT\n", stdout);
|
||||
exit(0);
|
||||
default:
|
||||
fprintf(stderr, "bad option %d\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (argc - optind != 2) {
|
||||
fputs("missing args\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
host = argv[optind + 0];
|
||||
port = argv[optind + 1];
|
||||
|
||||
switch ((rc = getaddrinfo(host, port, &hint, &ai))) {
|
||||
case EAI_SUCCESS:
|
||||
break;
|
||||
case EAI_SYSTEM:
|
||||
perror("getaddrinfo");
|
||||
exit(1);
|
||||
default:
|
||||
fputs("EAI_", stderr);
|
||||
fputs(gai_strerror(rc), stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) {
|
||||
perror("setsockopt(SO_LINGER)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
|
||||
perror("connect");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fds[0].fd = 0;
|
||||
fds[1].fd = sock;
|
||||
for (;;) {
|
||||
fds[0].revents = 0;
|
||||
fds[1].revents = 0;
|
||||
if (poll(fds, ARRAYLEN(fds), -1) == -1) {
|
||||
perror("poll");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fds[0].revents & (POLLIN | POLLERR | POLLHUP)) {
|
||||
if ((rc = read(0, buf, 1400)) == -1) {
|
||||
perror("read(stdin)");
|
||||
exit(1);
|
||||
}
|
||||
if (!(got = rc)) {
|
||||
if (halfclose) {
|
||||
shutdown(sock, SHUT_WR);
|
||||
}
|
||||
fds[0].fd = -1;
|
||||
}
|
||||
for (i = 0; i < got; i += rc) {
|
||||
if ((rc = write(sock, buf + i, got - i)) == -1) {
|
||||
perror("write(sock)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fds[1].revents & (POLLIN | POLLERR | POLLHUP)) {
|
||||
if ((rc = read(sock, buf, 1500)) == -1) {
|
||||
perror("read(sock)");
|
||||
exit(1);
|
||||
}
|
||||
if (!(got = rc)) {
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < got; i += rc) {
|
||||
if ((rc = write(1, buf + i, got - i)) == -1) {
|
||||
perror("write(stdout)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (close(sock) == -1) {
|
||||
perror("close");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return 0;
|
||||
}
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/ohmyplus/vector.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
#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/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.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 "tool/build/lib/panel.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Paneling Demo.
|
||||
*
|
||||
* This is useful for creating terminal user interfaces. We take the
|
||||
* simplest approach possible. The main thing we abstract is like,
|
||||
* truncating the lines that overflow within a panel. In order to do
|
||||
* that, we abstract the ANSI parsing and the implementation is able to
|
||||
* tell how many cells wide each UNICODE character is.
|
||||
*
|
||||
* There are smarter ways for Cosmopolitan to do this. For example, it'd
|
||||
* be great to have automatic flex boxes. It'd also be nice to be able
|
||||
* to use dynamic programming for low bandwidth display updates, like
|
||||
* Emacs does, but that's less of an issue these days and can actually
|
||||
* make things slower, since for heavy workloads like printing videos,
|
||||
* having ANSI codes bouncing around the display actually goes slower.
|
||||
*
|
||||
* Beyond basic paneling, a message box widget is also provided, which
|
||||
* makes it easier to do modal dialogs.
|
||||
*/
|
||||
|
||||
struct Panels {
|
||||
union {
|
||||
struct {
|
||||
struct Panel left;
|
||||
struct Panel right;
|
||||
};
|
||||
struct Panel p[2];
|
||||
};
|
||||
} pan;
|
||||
|
||||
long tyn;
|
||||
long txn;
|
||||
char key[8];
|
||||
bool shutdown;
|
||||
bool invalidated;
|
||||
struct termios oldterm;
|
||||
|
||||
void OnShutdown(int sig) {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
void OnInvalidate(int sig) {
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
void GetTtySize(void) {
|
||||
struct winsize wsize;
|
||||
wsize.ws_row = tyn;
|
||||
wsize.ws_col = txn;
|
||||
getttysize(1, &wsize);
|
||||
tyn = wsize.ws_row;
|
||||
txn = wsize.ws_col;
|
||||
}
|
||||
|
||||
int Write(const char *s) {
|
||||
return write(1, s, strlen(s));
|
||||
}
|
||||
|
||||
void Setup(void) {
|
||||
CHECK_NE(-1, ioctl(1, TCGETS, &oldterm));
|
||||
}
|
||||
|
||||
void Enter(void) {
|
||||
struct termios term;
|
||||
memcpy(&term, &oldterm, sizeof(term));
|
||||
term.c_cc[VMIN] = 1;
|
||||
term.c_cc[VTIME] = 1;
|
||||
term.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
|
||||
term.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
|
||||
term.c_cflag &= ~(CSIZE | PARENB);
|
||||
term.c_cflag |= CS8;
|
||||
term.c_iflag |= IUTF8;
|
||||
CHECK_NE(-1, ioctl(1, TCSETS, &term));
|
||||
Write("\e[?25l");
|
||||
}
|
||||
|
||||
void Leave(void) {
|
||||
Write(gc(xasprintf("\e[?25h\e[%d;%dH\e[S\r\n", tyn, txn)));
|
||||
ioctl(1, TCSETS, &oldterm);
|
||||
}
|
||||
|
||||
void Clear(void) {
|
||||
long i, j;
|
||||
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
|
||||
for (j = 0; j < pan.p[i].n; ++j) {
|
||||
free(pan.p[i].lines[j].p);
|
||||
}
|
||||
free(pan.p[i].lines);
|
||||
pan.p[i].lines = 0;
|
||||
pan.p[i].n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Layout(void) {
|
||||
long i, j;
|
||||
i = txn >> 1;
|
||||
pan.left.top = 0;
|
||||
pan.left.left = 0;
|
||||
pan.left.bottom = tyn;
|
||||
pan.left.right = i;
|
||||
pan.right.top = 0;
|
||||
pan.right.left = i + 1;
|
||||
pan.right.bottom = tyn;
|
||||
pan.right.right = txn;
|
||||
pan.left.n = pan.left.bottom - pan.left.top;
|
||||
pan.left.lines = xcalloc(pan.left.n, sizeof(*pan.left.lines));
|
||||
pan.right.n = pan.right.bottom - pan.right.top;
|
||||
pan.right.lines = xcalloc(pan.right.n, sizeof(*pan.right.lines));
|
||||
}
|
||||
|
||||
void Append(struct Panel *p, int i, const char *s) {
|
||||
if (i >= p->n) return;
|
||||
AppendStr(p->lines + i, s);
|
||||
}
|
||||
|
||||
void Draw(void) {
|
||||
Append(&pan.left, 0, gc(xasprintf("you typed %`'s", key)));
|
||||
Append(&pan.left, ((tyn + 1) >> 1) + 0, "hello left 1 𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷");
|
||||
Append(&pan.left, ((tyn + 1) >> 1) + 1, "hello left 2 (╯°□°)╯");
|
||||
Append(&pan.right, ((tyn + 1) >> 1) + 0, "hello right 1");
|
||||
Append(&pan.right, ((tyn + 1) >> 1) + 1, "hello right 2");
|
||||
PrintPanels(1, ARRAYLEN(pan.p), pan.p, tyn, txn);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sigaction sa[2] = {{.sa_handler = OnShutdown},
|
||||
{.sa_handler = OnInvalidate}};
|
||||
showcrashreports();
|
||||
Setup();
|
||||
Enter();
|
||||
GetTtySize();
|
||||
sigaction(SIGINT, &sa[0], 0);
|
||||
sigaction(SIGCONT, &sa[1], 0);
|
||||
sigaction(SIGWINCH, &sa[1], 0);
|
||||
atexit(Leave);
|
||||
do {
|
||||
Clear();
|
||||
Layout();
|
||||
Draw();
|
||||
if (invalidated) {
|
||||
Enter();
|
||||
GetTtySize();
|
||||
invalidated = false;
|
||||
} else {
|
||||
readansi(0, key, sizeof(key));
|
||||
}
|
||||
} while (!shutdown);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/runtime/interruptiblecall.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
struct InterruptibleCall icall;
|
||||
|
||||
static intptr_t peek(intptr_t *addr) {
|
||||
return *addr;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
intptr_t addr = strtoul(argv[i], NULL, 0);
|
||||
icall.sig = SIGSEGV;
|
||||
printf("%#p → %#lx\n", addr,
|
||||
interruptiblecall(&icall, (void *)peek, addr, 0, 0, 0));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pipefds[2] = {-1, -1};
|
||||
int rc = pipe(pipefds);
|
||||
printf("%d → %ld %ld\n", rc, pipefds[0], pipefds[1]);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,26 +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/bits/bits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc;
|
||||
int pollms = 1;
|
||||
struct pollfd fds[] = {{-1, 0}, {STDIN_FILENO, POLLIN}};
|
||||
if ((rc = poll(fds, ARRAYLEN(fds), pollms)) != -1) {
|
||||
printf("toto=%d\n", rc);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+41
-24
@@ -20,39 +20,56 @@ const struct AuxiliaryValue {
|
||||
const char *name;
|
||||
const char *description;
|
||||
} kAuxiliaryValues[] = {
|
||||
{"%p", &AT_EXECFD, "AT_EXECFD", "file descriptor of program"},
|
||||
{"%p", &AT_PHDR, "AT_PHDR", "address of elf program headers"},
|
||||
{"%p", &AT_PHENT, "AT_PHENT", "size of program header entry"},
|
||||
{"%p", &AT_PHNUM, "AT_PHNUM", "number of program headers"},
|
||||
{"%p", &AT_PAGESZ, "AT_PAGESZ", "system page size"},
|
||||
{"%p", &AT_BASE, "AT_BASE", "base address of the program interpreter"},
|
||||
{"%p", &AT_ENTRY, "AT_ENTRY", "entry address of executable"},
|
||||
{"%p", &AT_NOTELF, "AT_NOTELF", "set if not an elf"},
|
||||
{"%012lx", &AT_EXECFD, "AT_EXECFD", "file descriptor of program"},
|
||||
{"%012lx", &AT_PHDR, "AT_PHDR", "address of elf program headers"},
|
||||
{"%012lx", &AT_PHENT, "AT_PHENT", "size of program header entry"},
|
||||
{"%012lx", &AT_PHNUM, "AT_PHNUM", "number of program headers"},
|
||||
{"%012lx", &AT_PAGESZ, "AT_PAGESZ", "system page size"},
|
||||
{"%012lx", &AT_BASE, "AT_BASE", "base address of the program interpreter"},
|
||||
{"%012lx", &AT_ENTRY, "AT_ENTRY", "entry address of executable"},
|
||||
{"%012lx", &AT_NOTELF, "AT_NOTELF", "set if not an elf"},
|
||||
{"%-12d", &AT_UID, "AT_UID", "real user id of thread"},
|
||||
{"%-12d", &AT_EUID, "AT_EUID", "effective user id of thread"},
|
||||
{"%-12d", &AT_GID, "AT_GID", "real group id of thread"},
|
||||
{"%-12d", &AT_EGID, "AT_EGID", "effective group id of thread"},
|
||||
{"%-12d", &AT_CLKTCK, "AT_CLKTCK", "frequency of times() counts"},
|
||||
{"%p", &AT_OSRELDATE, "AT_OSRELDATE",
|
||||
{"%012lx", &AT_OSRELDATE, "AT_OSRELDATE",
|
||||
"freebsd release number, e.g. 1200086"},
|
||||
{"%p", &AT_PLATFORM, "AT_PLATFORM", "string identifying hardware platform"},
|
||||
{"%p", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE", "data cache block size"},
|
||||
{"%p", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE", "instruction cache block size"},
|
||||
{"%p", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE", "unified cache block size"},
|
||||
{"%p", &AT_SECURE, "AT_SECURE", "for set{u,g}id binz & security blankets"},
|
||||
{"%012lx", &AT_PLATFORM, "AT_PLATFORM",
|
||||
"string identifying hardware platform"},
|
||||
{"%012lx", &AT_DCACHEBSIZE, "AT_DCACHEBSIZE", "data cache block size"},
|
||||
{"%012lx", &AT_ICACHEBSIZE, "AT_ICACHEBSIZE",
|
||||
"instruction cache block size"},
|
||||
{"%012lx", &AT_UCACHEBSIZE, "AT_UCACHEBSIZE", "unified cache block size"},
|
||||
{"%012lx", &AT_SECURE, "AT_SECURE",
|
||||
"for set{u,g}id binz & security blankets"},
|
||||
{"%-12s", &AT_BASE_PLATFORM, "AT_BASE_PLATFORM",
|
||||
"string identifying real platform"},
|
||||
{"%p", &AT_RANDOM, "AT_RANDOM", "address of sixteen random bytes"},
|
||||
{"%012lx", &AT_RANDOM, "AT_RANDOM", "address of sixteen random bytes"},
|
||||
{"%-12s", &AT_EXECFN, "AT_EXECFN", "pathname used to execute program"},
|
||||
{"%p", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR",
|
||||
{"%012lx", &AT_SYSINFO_EHDR, "AT_SYSINFO_EHDR",
|
||||
"linux virtual dso page address"},
|
||||
{"%012lx", &AT_FLAGS, "AT_FLAGS", "unused?"},
|
||||
{"%012lx", &AT_HWCAP, "AT_HWCAP", "cpu stuff"},
|
||||
{"%012lx", &AT_HWCAP2, "AT_HWCAP2", "more cpu stuff"},
|
||||
};
|
||||
|
||||
const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
|
||||
int i;
|
||||
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
|
||||
if (x == *kAuxiliaryValues[i].id) {
|
||||
return kAuxiliaryValues + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char **envp) {
|
||||
long key;
|
||||
unsigned i;
|
||||
unsigned long val;
|
||||
unsigned long *auxp;
|
||||
char fmt[64], **env;
|
||||
struct AuxiliaryValue *auxinfo;
|
||||
printf("\nArguments:\n");
|
||||
for (i = 0; i < __argc; ++i) {
|
||||
printf(" ☼ %s\n", argv[i]);
|
||||
@@ -62,13 +79,13 @@ int main(int argc, char *argv[], char **envp) {
|
||||
printf(" ☼ %s\n", *env);
|
||||
}
|
||||
printf("\nAuxiliary Values:\n");
|
||||
for (i = 0; i < ARRAYLEN(kAuxiliaryValues); ++i) {
|
||||
key = *kAuxiliaryValues[i].id;
|
||||
val = getauxval(key);
|
||||
stpcpy(stpcpy(stpcpy(fmt, "%16s[%p] = "), kAuxiliaryValues[i].fmt),
|
||||
" # %s\n");
|
||||
printf(fmt, kAuxiliaryValues[i].name, key, val,
|
||||
kAuxiliaryValues[i].description);
|
||||
for (auxp = __auxv; *auxp; auxp += 2) {
|
||||
if ((auxinfo = DescribeAuxv(auxp[0]))) {
|
||||
stpcpy(stpcpy(stpcpy(fmt, "%16s[%4ld] = "), auxinfo->fmt), " # %s\n");
|
||||
printf(fmt, auxinfo->name, auxp[0], auxp[1], auxinfo->description);
|
||||
} else {
|
||||
printf("%16s[%4ld] = %012lx\n", "unknown", auxp[0], auxp[1]);
|
||||
}
|
||||
}
|
||||
printf("\nSpecial Directories:\n");
|
||||
printf(" ☼ kTmpPath = %`'s\n", kTmpPath);
|
||||
|
||||
@@ -1,26 +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 "dsp/tty/tty.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
setenv("GDB", "nopenopenope", true);
|
||||
showcrashreports();
|
||||
ttyraw(kTtyLfToCrLf | kTtySigs);
|
||||
printf("hi\n"), sleep(1);
|
||||
if (argc > 1 && strstr(argv[1], "crash")) abort();
|
||||
printf("there\n"), sleep(1);
|
||||
return 0;
|
||||
}
|
||||
+87
-28
@@ -8,58 +8,117 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
void Show(const char *name, long measurement, const char *unit) {
|
||||
fprintf(stderr, "%-*s%,*d %s\n", 32, name, 32, measurement, unit);
|
||||
#define PREFIX "\e[1mRL\e[0m: "
|
||||
|
||||
static void PrintResourceReport(struct rusage *ru) {
|
||||
long utime, stime;
|
||||
long double ticks;
|
||||
if (ru->ru_maxrss) {
|
||||
fprintf(stderr, "%sballooned to %,ldkb in size\n", PREFIX, ru->ru_maxrss);
|
||||
}
|
||||
if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) |
|
||||
(stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) {
|
||||
ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK));
|
||||
fprintf(stderr, "%sneeded %,ldµs cpu (%d%% kernel)\n", PREFIX,
|
||||
utime + stime, (int)((long double)stime / (utime + stime) * 100));
|
||||
if (ru->ru_idrss) {
|
||||
fprintf(stderr, "%sneeded %,ldkb memory on average\n", PREFIX,
|
||||
lroundl(ru->ru_idrss / ticks));
|
||||
}
|
||||
if (ru->ru_isrss) {
|
||||
fprintf(stderr, "%sneeded %,ldkb stack on average\n", PREFIX,
|
||||
lroundl(ru->ru_isrss / ticks));
|
||||
}
|
||||
if (ru->ru_ixrss) {
|
||||
fprintf(stderr, "%smapped %,ldkb shared on average\n", PREFIX,
|
||||
lroundl(ru->ru_ixrss / ticks));
|
||||
}
|
||||
}
|
||||
if (ru->ru_minflt || ru->ru_majflt) {
|
||||
fprintf(stderr, "%scaused %,ld page faults (%d%% memcpy)\n", PREFIX,
|
||||
ru->ru_minflt + ru->ru_majflt,
|
||||
(int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) *
|
||||
100));
|
||||
}
|
||||
if (ru->ru_nvcsw + ru->ru_nivcsw > 1) {
|
||||
fprintf(stderr, "%s%,ld context switches (%d%% consensual)\n", PREFIX,
|
||||
ru->ru_nvcsw + ru->ru_nivcsw,
|
||||
(int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) *
|
||||
100));
|
||||
}
|
||||
if (ru->ru_msgrcv || ru->ru_msgsnd) {
|
||||
fprintf(stderr, "%sreceived %,ld message%s and sent %,ld\n", PREFIX,
|
||||
ru->ru_msgrcv, ru->ru_msgrcv == 1 ? "" : "s", ru->ru_msgsnd);
|
||||
}
|
||||
if (ru->ru_inblock || ru->ru_oublock) {
|
||||
fprintf(stderr, "%sperformed %,ld read%s and %,ld write i/o operations\n",
|
||||
PREFIX, ru->ru_inblock, ru->ru_inblock == 1 ? "" : "s",
|
||||
ru->ru_oublock);
|
||||
}
|
||||
if (ru->ru_nsignals) {
|
||||
fprintf(stderr, "%sreceived %,ld signals\n", PREFIX, ru->ru_nsignals);
|
||||
}
|
||||
if (ru->ru_nswap) {
|
||||
fprintf(stderr, "%sgot swapped %,ld times\n", PREFIX, ru->ru_nswap);
|
||||
}
|
||||
}
|
||||
|
||||
long TvToNs(struct timeval tv) {
|
||||
return tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
|
||||
}
|
||||
struct rusage rusage;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid, wstatus;
|
||||
long double ts1, ts2;
|
||||
struct rusage rusage;
|
||||
sigset_t chldmask, savemask;
|
||||
struct sigaction dflt, ignore, saveint, savequit;
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s PROG [ARGS...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
memset(&rusage, -1, sizeof(rusage));
|
||||
CHECK_GT(argc, 1);
|
||||
dflt.sa_flags = 0;
|
||||
dflt.sa_handler = SIG_DFL;
|
||||
sigemptyset(&dflt.sa_mask);
|
||||
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);
|
||||
ts1 = nowl();
|
||||
if (!(pid = vfork())) {
|
||||
CHECK_NE(-1, (pid = vfork()));
|
||||
if (!pid) {
|
||||
sigaction(SIGINT, &dflt, 0);
|
||||
sigaction(SIGQUIT, &dflt, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
execvp(argv[1], argv + 1);
|
||||
abort();
|
||||
fprintf(stderr, "exec failed %d\n", errno);
|
||||
_Exit(127);
|
||||
}
|
||||
while (wait4(pid, &wstatus, 0, &rusage) == -1) {
|
||||
CHECK_EQ(EINTR, errno);
|
||||
}
|
||||
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));
|
||||
ts2 = nowl();
|
||||
Show("wall time", lroundl((ts2 - ts1) * 1e9l), "ns");
|
||||
Show("user time", TvToNs(rusage.ru_utime), "ns");
|
||||
Show("sys time", TvToNs(rusage.ru_stime), "ns");
|
||||
Show("maximum resident set size", rusage.ru_maxrss, "");
|
||||
Show("integral shared memory size", rusage.ru_ixrss, "");
|
||||
Show("integral unshared data size", rusage.ru_idrss, "");
|
||||
Show("integral unshared stack size", rusage.ru_isrss, "");
|
||||
Show("minor page faults", rusage.ru_minflt, "");
|
||||
Show("major page faults", rusage.ru_majflt, "");
|
||||
Show("swaps", rusage.ru_nswap, "");
|
||||
Show("block input ops", rusage.ru_inblock, "");
|
||||
Show("block output ops", rusage.ru_oublock, "");
|
||||
Show("ipc messages sent", rusage.ru_msgsnd, "");
|
||||
Show("ipc messages received", rusage.ru_msgrcv, "");
|
||||
Show("signals received", rusage.ru_nsignals, "");
|
||||
Show("voluntary context switches", rusage.ru_nvcsw, "");
|
||||
Show("involuntary context switches", rusage.ru_nivcsw, "");
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
fprintf(stderr, "%stook %,ldµs wall time\n", PREFIX,
|
||||
(int64_t)((ts2 - ts1) * 1e6));
|
||||
PrintResourceReport(&rusage);
|
||||
if (WIFEXITED(wstatus)) {
|
||||
return WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
|
||||
@@ -1,23 +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/runtime/runtime.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid, wstatus;
|
||||
if (argc < 2) return 1;
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
execv(argv[1], argv + 1);
|
||||
abort();
|
||||
}
|
||||
waitpid(pid, &wstatus, 0);
|
||||
return WEXITSTATUS(wstatus);
|
||||
}
|
||||
+3
-3
@@ -44,9 +44,9 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
|
||||
"hard link count", st->st_nlink, "mode / permissions", st->st_mode,
|
||||
"owner id", st->st_uid, "group id", st->st_gid,
|
||||
"device id (if special)", st->st_rdev, "block size", st->st_blksize,
|
||||
"access time", gc(xiso8601(&st->st_atim)), "modified time",
|
||||
gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
|
||||
gc(xiso8601(&st->st_ctim)));
|
||||
"access time", _gc(xiso8601(&st->st_atim)), "modified time",
|
||||
_gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
|
||||
_gc(xiso8601(&st->st_ctim)));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@@ -1,18 +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/stat.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct stat st;
|
||||
st.st_size = -1;
|
||||
stat(argv[1], &st);
|
||||
return st.st_size;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#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/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/stdio/append.internal.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Fast Growable Strings Tutorial
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *b = 0;
|
||||
appendf(&b, "hello "); // guarantees nul terminator
|
||||
CHECK_EQ(6, strlen(b));
|
||||
CHECK_EQ(6, appendz(b).i);
|
||||
appendf(&b, " world\n");
|
||||
CHECK_EQ(13, strlen(b));
|
||||
CHECK_EQ(13, appendz(b).i);
|
||||
appendd(&b, "\0", 1); // supports binary
|
||||
CHECK_EQ(13, strlen(b));
|
||||
CHECK_EQ(14, appendz(b).i);
|
||||
appendf(&b, "%d arg%s\n", argc, argc == 1 ? "" : "s");
|
||||
appendf(&b, "%s\n", "have a nice day");
|
||||
write(1, b, appendz(b).i);
|
||||
free(b);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,67 +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/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned need = 0;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "hasnrvmd")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
need |= 0b111111;
|
||||
break;
|
||||
case 's':
|
||||
need |= 0b000001;
|
||||
break;
|
||||
case 'n':
|
||||
need |= 0b000010;
|
||||
break;
|
||||
case 'r':
|
||||
need |= 0b000100;
|
||||
break;
|
||||
case 'v':
|
||||
need |= 0b001000;
|
||||
break;
|
||||
case 'm':
|
||||
need |= 0b010000;
|
||||
break;
|
||||
case 'd':
|
||||
need |= 0b100000;
|
||||
break;
|
||||
default: /* -? or -h */
|
||||
fprintf(stderr, "%s: %s [%s]\n%s", "Usage", argv[0], "FLAGS",
|
||||
" -a\tprint all\n"
|
||||
" -s\tprint sysname\n"
|
||||
" -n\tprint nodename\n"
|
||||
" -r\tprint release\n"
|
||||
" -v\tprint version\n"
|
||||
" -m\tprint machine\n"
|
||||
" -d\tprint domainname\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (!need) need = 0b000001;
|
||||
struct utsname data;
|
||||
if (uname(&data) == -1) perror("uname"), exit(EXIT_FAILURE);
|
||||
if (need & 0b000001) printf("%s ", data.sysname);
|
||||
if (need & 0b000010) printf("%s ", data.nodename);
|
||||
if (need & 0b000100) printf("%s ", data.release);
|
||||
if (need & 0b001000) printf("%s ", data.version);
|
||||
if (need & 0b010000) printf("%s ", data.machine);
|
||||
if (need & 0b100000) printf("%s ", data.domainname);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/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/x/x.h"
|
||||
#include "third_party/musl/ftw.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Directory walker example.
|
||||
* Copied from IEEE Std 1003.1-2017
|
||||
*/
|
||||
|
||||
static int display_info(const char *fpath, const struct stat *sb, int tflag,
|
||||
struct FTW *ftwbuf) {
|
||||
printf("%-3s %2d %7jd %-40s %d %s\n",
|
||||
(tflag == FTW_D) ? "d"
|
||||
: (tflag == FTW_DNR) ? "dnr"
|
||||
: (tflag == FTW_DP) ? "dp"
|
||||
: (tflag == FTW_F) ? (S_ISBLK(sb->st_mode) ? "f b"
|
||||
: S_ISCHR(sb->st_mode) ? "f c"
|
||||
: S_ISFIFO(sb->st_mode) ? "f p"
|
||||
: S_ISREG(sb->st_mode) ? "f r"
|
||||
: S_ISSOCK(sb->st_mode) ? "f s"
|
||||
: "f ?")
|
||||
: (tflag == FTW_NS) ? "ns"
|
||||
: (tflag == FTW_SL) ? "sl"
|
||||
: (tflag == FTW_SLN) ? "sln"
|
||||
: "?",
|
||||
ftwbuf->level, (intmax_t)sb->st_size, fpath, ftwbuf->base,
|
||||
fpath + ftwbuf->base);
|
||||
return 0; /* To tell nftw() to continue */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int flags = 0;
|
||||
const char *dir;
|
||||
if (argc > 2 && strchr(argv[2], 'd') != NULL) flags |= FTW_DEPTH;
|
||||
if (argc > 2 && strchr(argv[2], 'p') != NULL) flags |= FTW_PHYS;
|
||||
dir = argc < 2 ? "." : argv[1];
|
||||
if (nftw(dir, display_info, 20, flags) == -1) {
|
||||
fprintf(stderr, "nftw() failed: %s: %s\n", strerror(errno), dir);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -16,6 +16,24 @@
|
||||
|
||||
/**
|
||||
* @fileoverview x86 instruction length decoder by way of hex pipe.
|
||||
*
|
||||
* Here's an example of how you can use it to decode a NOP stream:
|
||||
*
|
||||
* $ make -j8 o//examples/x86split.com
|
||||
* $ echo 909090 | o//examples/x86split.com
|
||||
* 90
|
||||
* 90
|
||||
* 90
|
||||
*
|
||||
* If there was a XOR instruction in there, it'd do this:
|
||||
*
|
||||
* $ make -j8 o//examples/x86split.com
|
||||
* $ echo 904531FF90 | o//examples/x86split.com
|
||||
* 90 # NOP
|
||||
* 4531FF # XOR R15D,R15D
|
||||
* 90 # NOP
|
||||
*
|
||||
* Now that you're able to split x86 instructions the rest is easy.
|
||||
*/
|
||||
|
||||
int fgethex(FILE *f) {
|
||||
|
||||
+17
-13
@@ -6,19 +6,23 @@ COSMOPOLITAN_C_START_
|
||||
forceinline void *bisect(const void *k, const void *data, size_t n, size_t size,
|
||||
int cmp(const void *a, const void *b, void *arg),
|
||||
void *arg) {
|
||||
int dir;
|
||||
const char *p, *pos;
|
||||
p = data;
|
||||
while (n > 0) {
|
||||
pos = p + size * (n / 2);
|
||||
dir = cmp(k, pos, arg);
|
||||
if (dir < 0) {
|
||||
n /= 2;
|
||||
} else if (dir > 0) {
|
||||
p = pos + size;
|
||||
n -= n / 2 + 1;
|
||||
} else {
|
||||
return (void *)pos;
|
||||
int c;
|
||||
const char *p;
|
||||
ssize_t m, l, r;
|
||||
if (n) {
|
||||
l = 0;
|
||||
r = n - 1;
|
||||
p = data;
|
||||
while (l <= r) {
|
||||
m = (l + r) >> 1;
|
||||
c = cmp(k, p + m * size, arg);
|
||||
if (c > 0) {
|
||||
l = m + 1;
|
||||
} else if (c < 0) {
|
||||
r = m - 1;
|
||||
} else {
|
||||
return p + m * size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
+4
-9
@@ -6,18 +6,13 @@ COSMOPOLITAN_C_START_
|
||||
void __assert_fail(const char *, const char *, int) hidden wontreturn relegated;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define __ASSERT_FAIL(EXPR, FILE, LINE)
|
||||
#define assert(EXPR) ((void)0)
|
||||
#else
|
||||
#define __ASSERT_FAIL(EXPR, FILE, LINE) __assert_fail(EXPR, FILE, LINE)
|
||||
#define assert(EXPR) \
|
||||
((void)((EXPR) || (__assert_fail(#EXPR, __FILE__, __LINE__), 0)))
|
||||
#endif
|
||||
|
||||
#define assert(EXPR) \
|
||||
do { \
|
||||
if (!(EXPR)) { \
|
||||
__ASSERT_FAIL(#EXPR, __FILE__, __LINE__); \
|
||||
unreachable; \
|
||||
} \
|
||||
} while (0)
|
||||
#define static_assert _Static_assert
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@
|
||||
/**
|
||||
* Returns absolute value of x.
|
||||
*/
|
||||
int(abs)(int x) {
|
||||
int abs(int x) {
|
||||
return ABS(x);
|
||||
}
|
||||
@@ -21,6 +21,6 @@
|
||||
/**
|
||||
* Reverses bits in 16-bit word.
|
||||
*/
|
||||
uint16_t(bitreverse16)(uint16_t x) {
|
||||
return kReverseBits[x & 0x00FF] << 8 | kReverseBits[(x & 0xFF00) >> 8];
|
||||
int bitreverse16(int x) {
|
||||
return BITREVERSE16(x);
|
||||
}
|
||||
@@ -22,10 +22,10 @@
|
||||
/**
|
||||
* Reverses bits in 32-bit word.
|
||||
*/
|
||||
uint32_t(bitreverse32)(uint32_t x) {
|
||||
uint32_t bitreverse32(uint32_t x) {
|
||||
x = bswap_32(x);
|
||||
x = ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1);
|
||||
x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2);
|
||||
x = ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4);
|
||||
x = (x & 0xaaaaaaaa) >> 1 | (x & 0x55555555) << 1;
|
||||
x = (x & 0xcccccccc) >> 2 | (x & 0x33333333) << 2;
|
||||
x = (x & 0xf0f0f0f0) >> 4 | (x & 0x0f0f0f0f) << 4;
|
||||
return x;
|
||||
}
|
||||
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
uint64_t bitreverse64(uint64_t x) {
|
||||
x = bswap_64(x);
|
||||
x = ((x & 0xaaaaaaaaaaaaaaaa) >> 1) | ((x & 0x5555555555555555) << 1);
|
||||
x = ((x & 0xcccccccccccccccc) >> 2) | ((x & 0x3333333333333333) << 2);
|
||||
x = ((x & 0xf0f0f0f0f0f0f0f0) >> 4) | ((x & 0x0f0f0f0f0f0f0f0f) << 4);
|
||||
x = (x & 0xaaaaaaaaaaaaaaaa) >> 1 | (x & 0x5555555555555555) << 1;
|
||||
x = (x & 0xcccccccccccccccc) >> 2 | (x & 0x3333333333333333) << 2;
|
||||
x = (x & 0xf0f0f0f0f0f0f0f0) >> 4 | (x & 0x0f0f0f0f0f0f0f0f) << 4;
|
||||
return x;
|
||||
}
|
||||
@@ -21,6 +21,6 @@
|
||||
/**
|
||||
* Reverses bits in 8-bit word.
|
||||
*/
|
||||
uint8_t(bitreverse8)(uint8_t x) {
|
||||
return kReverseBits[x];
|
||||
int bitreverse8(int x) {
|
||||
return BITREVERSE8(x);
|
||||
}
|
||||
+98
-100
@@ -13,8 +13,8 @@ extern const uint8_t kReverseBits[256];
|
||||
|
||||
uint32_t gray(uint32_t) pureconst;
|
||||
uint32_t ungray(uint32_t) pureconst;
|
||||
uint8_t bitreverse8(uint8_t) libcesque pureconst;
|
||||
uint16_t bitreverse16(uint16_t) libcesque pureconst;
|
||||
int bitreverse8(int) libcesque pureconst;
|
||||
int bitreverse16(int) libcesque pureconst;
|
||||
uint32_t bitreverse32(uint32_t) libcesque pureconst;
|
||||
uint64_t bitreverse64(uint64_t) libcesque pureconst;
|
||||
unsigned long roundup2pow(unsigned long) libcesque pureconst;
|
||||
@@ -31,106 +31,104 @@ intptr_t atomic_store(void *, intptr_t, size_t);
|
||||
│ cosmopolitan § bits » no assembly required ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define bitreverse8(X) (kReverseBits[(uint8_t)(X)])
|
||||
#define bitreverse16(X) \
|
||||
((uint16_t)kReverseBits[(uint8_t)(X)] << 010 | \
|
||||
kReverseBits[((uint16_t)(X) >> 010) & 0xff])
|
||||
#define BITREVERSE8(X) (kReverseBits[255 & (X)])
|
||||
#define BITREVERSE16(X) \
|
||||
(kReverseBits[0x00FF & (X)] << 8 | kReverseBits[(0xFF00 & (X)) >> 8])
|
||||
|
||||
#define READ16LE(S) \
|
||||
((uint16_t)((unsigned char *)(S))[1] << 010 | \
|
||||
(uint16_t)((unsigned char *)(S))[0] << 000)
|
||||
#define READ32LE(S) \
|
||||
((uint32_t)((unsigned char *)(S))[3] << 030 | \
|
||||
(uint32_t)((unsigned char *)(S))[2] << 020 | \
|
||||
(uint32_t)((unsigned char *)(S))[1] << 010 | \
|
||||
(uint32_t)((unsigned char *)(S))[0] << 000)
|
||||
#define READ64LE(S) \
|
||||
((uint64_t)((unsigned char *)(S))[7] << 070 | \
|
||||
(uint64_t)((unsigned char *)(S))[6] << 060 | \
|
||||
(uint64_t)((unsigned char *)(S))[5] << 050 | \
|
||||
(uint64_t)((unsigned char *)(S))[4] << 040 | \
|
||||
(uint64_t)((unsigned char *)(S))[3] << 030 | \
|
||||
(uint64_t)((unsigned char *)(S))[2] << 020 | \
|
||||
(uint64_t)((unsigned char *)(S))[1] << 010 | \
|
||||
(uint64_t)((unsigned char *)(S))[0] << 000)
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define READ16LE(S) ((255 & (S)[1]) << 8 | (255 & (S)[0]))
|
||||
#define READ16BE(S) ((255 & (S)[0]) << 8 | (255 & (S)[1]))
|
||||
#define READ32LE(S) \
|
||||
((uint32_t)(255 & (S)[3]) << 030 | (uint32_t)(255 & (S)[2]) << 020 | \
|
||||
(uint32_t)(255 & (S)[1]) << 010 | (uint32_t)(255 & (S)[0]) << 000)
|
||||
#define READ32BE(S) \
|
||||
((uint32_t)(255 & (S)[0]) << 030 | (uint32_t)(255 & (S)[1]) << 020 | \
|
||||
(uint32_t)(255 & (S)[2]) << 010 | (uint32_t)(255 & (S)[3]) << 000)
|
||||
#define READ64LE(S) \
|
||||
((uint64_t)(255 & (S)[7]) << 070 | (uint64_t)(255 & (S)[6]) << 060 | \
|
||||
(uint64_t)(255 & (S)[5]) << 050 | (uint64_t)(255 & (S)[4]) << 040 | \
|
||||
(uint64_t)(255 & (S)[3]) << 030 | (uint64_t)(255 & (S)[2]) << 020 | \
|
||||
(uint64_t)(255 & (S)[1]) << 010 | (uint64_t)(255 & (S)[0]) << 000)
|
||||
#define READ64BE(S) \
|
||||
((uint64_t)(255 & (S)[0]) << 070 | (uint64_t)(255 & (S)[1]) << 060 | \
|
||||
(uint64_t)(255 & (S)[2]) << 050 | (uint64_t)(255 & (S)[3]) << 040 | \
|
||||
(uint64_t)(255 & (S)[4]) << 030 | (uint64_t)(255 & (S)[5]) << 020 | \
|
||||
(uint64_t)(255 & (S)[6]) << 010 | (uint64_t)(255 & (S)[7]) << 000)
|
||||
#else /* gcc needs help knowing above are mov if s isn't a variable */
|
||||
#define READ16LE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
Ptr[1] << 8 | Ptr[0]; \
|
||||
})
|
||||
#define READ16BE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
Ptr[0] << 8 | Ptr[1]; \
|
||||
})
|
||||
#define READ32LE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
((uint32_t)Ptr[3] << 030 | (uint32_t)Ptr[2] << 020 | \
|
||||
(uint32_t)Ptr[1] << 010 | (uint32_t)Ptr[0] << 000); \
|
||||
})
|
||||
#define READ32BE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
((uint32_t)Ptr[0] << 030 | (uint32_t)Ptr[1] << 020 | \
|
||||
(uint32_t)Ptr[2] << 010 | (uint32_t)Ptr[3] << 000); \
|
||||
})
|
||||
#define READ64LE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
((uint64_t)Ptr[7] << 070 | (uint64_t)Ptr[6] << 060 | \
|
||||
(uint64_t)Ptr[5] << 050 | (uint64_t)Ptr[4] << 040 | \
|
||||
(uint64_t)Ptr[3] << 030 | (uint64_t)Ptr[2] << 020 | \
|
||||
(uint64_t)Ptr[1] << 010 | (uint64_t)Ptr[0] << 000); \
|
||||
})
|
||||
#define READ64BE(S) \
|
||||
({ \
|
||||
const uint8_t *Ptr = (const uint8_t *)(S); \
|
||||
((uint64_t)Ptr[0] << 070 | (uint64_t)Ptr[1] << 060 | \
|
||||
(uint64_t)Ptr[2] << 050 | (uint64_t)Ptr[3] << 040 | \
|
||||
(uint64_t)Ptr[4] << 030 | (uint64_t)Ptr[5] << 020 | \
|
||||
(uint64_t)Ptr[6] << 010 | (uint64_t)Ptr[7] << 000); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define READ16BE(S) \
|
||||
((uint16_t)((unsigned char *)(S))[0] << 010 | \
|
||||
(uint16_t)((unsigned char *)(S))[1] << 000)
|
||||
#define READ32BE(S) \
|
||||
((uint32_t)((unsigned char *)(S))[0] << 030 | \
|
||||
(uint32_t)((unsigned char *)(S))[1] << 020 | \
|
||||
(uint32_t)((unsigned char *)(S))[2] << 010 | \
|
||||
(uint32_t)((unsigned char *)(S))[3] << 000)
|
||||
#define READ64BE(S) \
|
||||
((uint64_t)((unsigned char *)(S))[0] << 070 | \
|
||||
(uint64_t)((unsigned char *)(S))[1] << 060 | \
|
||||
(uint64_t)((unsigned char *)(S))[2] << 050 | \
|
||||
(uint64_t)((unsigned char *)(S))[3] << 040 | \
|
||||
(uint64_t)((unsigned char *)(S))[4] << 030 | \
|
||||
(uint64_t)((unsigned char *)(S))[5] << 020 | \
|
||||
(uint64_t)((unsigned char *)(S))[6] << 010 | \
|
||||
(uint64_t)((unsigned char *)(S))[7] << 000)
|
||||
|
||||
#define WRITE16LE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint16_t Vle = (V); \
|
||||
Ple[0] = (uint8_t)(Vle >> 000); \
|
||||
Ple[1] = (uint8_t)(Vle >> 010); \
|
||||
} while (0)
|
||||
#define WRITE32LE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint32_t Vle = (V); \
|
||||
Ple[0] = (uint8_t)(Vle >> 000); \
|
||||
Ple[1] = (uint8_t)(Vle >> 010); \
|
||||
Ple[2] = (uint8_t)(Vle >> 020); \
|
||||
Ple[3] = (uint8_t)(Vle >> 030); \
|
||||
} while (0)
|
||||
#define WRITE64LE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint64_t Vle = (V); \
|
||||
Ple[0] = (uint8_t)(Vle >> 000); \
|
||||
Ple[1] = (uint8_t)(Vle >> 010); \
|
||||
Ple[2] = (uint8_t)(Vle >> 020); \
|
||||
Ple[3] = (uint8_t)(Vle >> 030); \
|
||||
Ple[4] = (uint8_t)(Vle >> 040); \
|
||||
Ple[5] = (uint8_t)(Vle >> 050); \
|
||||
Ple[6] = (uint8_t)(Vle >> 060); \
|
||||
Ple[7] = (uint8_t)(Vle >> 070); \
|
||||
} while (0)
|
||||
|
||||
#define WRITE16BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint16_t Vle = (V); \
|
||||
Ple[1] = (uint8_t)(Vle >> 000); \
|
||||
Ple[0] = (uint8_t)(Vle >> 010); \
|
||||
} while (0)
|
||||
#define WRITE32BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint32_t Vle = (V); \
|
||||
Ple[3] = (uint8_t)(Vle >> 000); \
|
||||
Ple[2] = (uint8_t)(Vle >> 010); \
|
||||
Ple[1] = (uint8_t)(Vle >> 020); \
|
||||
Ple[0] = (uint8_t)(Vle >> 030); \
|
||||
} while (0)
|
||||
#define WRITE64BE(P, V) \
|
||||
do { \
|
||||
uint8_t *Ple = (uint8_t *)(P); \
|
||||
uint64_t Vle = (V); \
|
||||
Ple[7] = (uint8_t)(Vle >> 000); \
|
||||
Ple[6] = (uint8_t)(Vle >> 010); \
|
||||
Ple[5] = (uint8_t)(Vle >> 020); \
|
||||
Ple[4] = (uint8_t)(Vle >> 030); \
|
||||
Ple[3] = (uint8_t)(Vle >> 040); \
|
||||
Ple[2] = (uint8_t)(Vle >> 050); \
|
||||
Ple[1] = (uint8_t)(Vle >> 060); \
|
||||
Ple[0] = (uint8_t)(Vle >> 070); \
|
||||
} while (0)
|
||||
#define WRITE16LE(P, V) \
|
||||
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
|
||||
(P)[1] = (0x000000000000FF00 & (V)) >> 010, (P) + 2)
|
||||
#define WRITE16BE(P, V) \
|
||||
((P)[0] = (0x000000000000FF00 & (V)) >> 010, \
|
||||
(P)[1] = (0x00000000000000FF & (V)) >> 000, (P) + 2)
|
||||
#define WRITE32LE(P, V) \
|
||||
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
|
||||
(P)[1] = (0x000000000000FF00 & (V)) >> 010, \
|
||||
(P)[2] = (0x0000000000FF0000 & (V)) >> 020, \
|
||||
(P)[3] = (0x00000000FF000000 & (V)) >> 030, (P) + 4)
|
||||
#define WRITE32BE(P, V) \
|
||||
((P)[0] = (0x00000000FF000000 & (V)) >> 030, \
|
||||
(P)[1] = (0x0000000000FF0000 & (V)) >> 020, \
|
||||
(P)[2] = (0x000000000000FF00 & (V)) >> 010, \
|
||||
(P)[3] = (0x00000000000000FF & (V)) >> 000, (P) + 4)
|
||||
#define WRITE64LE(P, V) \
|
||||
((P)[0] = (0x00000000000000FF & (V)) >> 000, \
|
||||
(P)[1] = (0x000000000000FF00 & (V)) >> 010, \
|
||||
(P)[2] = (0x0000000000FF0000 & (V)) >> 020, \
|
||||
(P)[3] = (0x00000000FF000000 & (V)) >> 030, \
|
||||
(P)[4] = (0x000000FF00000000 & (V)) >> 040, \
|
||||
(P)[5] = (0x0000FF0000000000 & (V)) >> 050, \
|
||||
(P)[6] = (0x00FF000000000000 & (V)) >> 060, \
|
||||
(P)[7] = (0xFF00000000000000 & (V)) >> 070, (P) + 8)
|
||||
#define WRITE64BE(P, V) \
|
||||
((P)[0] = (0xFF00000000000000 & (V)) >> 070, \
|
||||
(P)[1] = (0x00FF000000000000 & (V)) >> 060, \
|
||||
(P)[2] = (0x0000FF0000000000 & (V)) >> 050, \
|
||||
(P)[3] = (0x000000FF00000000 & (V)) >> 040, \
|
||||
(P)[4] = (0x00000000FF000000 & (V)) >> 030, \
|
||||
(P)[5] = (0x0000000000FF0000 & (V)) >> 020, \
|
||||
(P)[6] = (0x000000000000FF00 & (V)) >> 010, \
|
||||
(P)[7] = (0x00000000000000FF & (V)) >> 000, (P) + 8)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § bits » some assembly required ─╬─│┼
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_BITS_NEWBIE_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_NEWBIE_H_
|
||||
#include "libc/bits/bswap.h"
|
||||
|
||||
/*
|
||||
* Macros for newbies.
|
||||
* https://justine.lol/endian.html
|
||||
*/
|
||||
|
||||
#define BYTE_ORDER __BYTE_ORDER__
|
||||
#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
|
||||
#define BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#define PDP_ENDIAN __ORDER_PDP_ENDIAN__
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define htobe16(x) bswap_16(x)
|
||||
#define be16toh(x) bswap_16(x)
|
||||
#define betoh16(x) bswap_16(x)
|
||||
#define htobe32(x) bswap_32(x)
|
||||
#define be32toh(x) bswap_32(x)
|
||||
#define betoh32(x) bswap_32(x)
|
||||
#define htobe64(x) bswap_64(x)
|
||||
#define be64toh(x) bswap_64(x)
|
||||
#define betoh64(x) bswap_64(x)
|
||||
#define htole16(x) (uint16_t)(x)
|
||||
#define le16toh(x) (uint16_t)(x)
|
||||
#define letoh16(x) (uint16_t)(x)
|
||||
#define htole32(x) (uint32_t)(x)
|
||||
#define le32toh(x) (uint32_t)(x)
|
||||
#define letoh32(x) (uint32_t)(x)
|
||||
#define htole64(x) (uint64_t)(x)
|
||||
#define le64toh(x) (uint64_t)(x)
|
||||
#define letoh64(x) (uint64_t)(x)
|
||||
#else
|
||||
#define htobe16(x) (uint16_t)(x)
|
||||
#define be16toh(x) (uint16_t)(x)
|
||||
#define betoh16(x) (uint16_t)(x)
|
||||
#define htobe32(x) (uint32_t)(x)
|
||||
#define be32toh(x) (uint32_t)(x)
|
||||
#define betoh32(x) (uint32_t)(x)
|
||||
#define htobe64(x) (uint64_t)(x)
|
||||
#define be64toh(x) (uint64_t)(x)
|
||||
#define betoh64(x) (uint64_t)(x)
|
||||
#define htole16(x) bswap_16(x)
|
||||
#define le16toh(x) bswap_16(x)
|
||||
#define letoh16(x) bswap_16(x)
|
||||
#define htole32(x) bswap_32(x)
|
||||
#define le32toh(x) bswap_32(x)
|
||||
#define letoh32(x) bswap_32(x)
|
||||
#define htole64(x) bswap_64(x)
|
||||
#define le64toh(x) bswap_64(x)
|
||||
#define letoh64(x) bswap_64(x)
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_NEWBIE_H_ */
|
||||
+9
-9
@@ -7,15 +7,15 @@ COSMOPOLITAN_C_START_
|
||||
unsigned long popcnt(unsigned long) pureconst;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define popcnt(X) \
|
||||
(__builtin_constant_p(X) ? __builtin_popcountll(X) : ({ \
|
||||
unsigned long Res, Pop = (X); \
|
||||
if (X86_HAVE(POPCNT)) { \
|
||||
asm("popcnt\t%1,%0" : "=r"(Res) : "r"(Pop) : "cc"); \
|
||||
} else { \
|
||||
Res = (popcnt)(Pop); \
|
||||
} \
|
||||
Res; \
|
||||
#define popcnt(X) \
|
||||
(__builtin_constant_p(X) ? __builtin_popcountll(X) : ({ \
|
||||
unsigned long PoP = (X); \
|
||||
if (X86_HAVE(POPCNT)) { \
|
||||
asm("popcnt\t%0,%0" : "+r"(PoP) : /* no inputs */ : "cc"); \
|
||||
} else { \
|
||||
PoP = (popcnt)(PoP); \
|
||||
} \
|
||||
PoP; \
|
||||
}))
|
||||
#endif /* GNUC && !ANSI */
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
void AddRusage(struct rusage *x, const struct rusage *y) {
|
||||
AddTimeval(&x->ru_utime, &y->ru_utime);
|
||||
AddTimeval(&x->ru_stime, &y->ru_stime);
|
||||
x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss);
|
||||
x->ru_ixrss += y->ru_ixrss;
|
||||
x->ru_idrss += y->ru_idrss;
|
||||
x->ru_isrss += y->ru_isrss;
|
||||
x->ru_minflt += y->ru_minflt;
|
||||
x->ru_majflt += y->ru_majflt;
|
||||
x->ru_nswap += y->ru_nswap;
|
||||
x->ru_inblock += y->ru_inblock;
|
||||
x->ru_oublock += y->ru_oublock;
|
||||
x->ru_msgsnd += y->ru_msgsnd;
|
||||
x->ru_msgrcv += y->ru_msgrcv;
|
||||
x->ru_nsignals += y->ru_nsignals;
|
||||
x->ru_nvcsw += y->ru_nvcsw;
|
||||
x->ru_nivcsw += y->ru_nivcsw;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
|
||||
void AddTimeval(struct timeval *x, const struct timeval *y) {
|
||||
x->tv_sec += y->tv_sec;
|
||||
x->tv_usec += y->tv_usec;
|
||||
if (x->tv_usec >= 1000000) {
|
||||
x->tv_usec -= 1000000;
|
||||
x->tv_sec += 1;
|
||||
}
|
||||
}
|
||||
+22
-19
@@ -5,6 +5,7 @@
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigval.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/sysinfo.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
@@ -29,7 +30,7 @@
|
||||
#define SIG_DFL ((void *)0)
|
||||
#define SIG_IGN ((void *)1)
|
||||
|
||||
#define MAP_FAILED ((void *)__SIZE_MAX__)
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_SET_FS 0x1002
|
||||
@@ -64,9 +65,6 @@ COSMOPOLITAN_C_START_
|
||||
|
||||
typedef int sig_atomic_t;
|
||||
|
||||
extern const struct sigset kSigsetFull;
|
||||
extern const struct sigset kSigsetEmpty;
|
||||
|
||||
DIR *fdopendir(int) nodiscard;
|
||||
DIR *opendir(const char *) nodiscard;
|
||||
bool fileexists(const char *);
|
||||
@@ -86,6 +84,7 @@ int arch_prctl();
|
||||
int chdir(const char *);
|
||||
int chmod(const char *, uint32_t);
|
||||
int chown(const char *, uint32_t, uint32_t);
|
||||
int chroot(const char *);
|
||||
int close(int);
|
||||
int closedir(DIR *);
|
||||
int creat(const char *, uint32_t) nodiscard;
|
||||
@@ -102,6 +101,7 @@ int execvp(const char *, char *const[]) paramsnonnull();
|
||||
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int faccessat(int, const char *, int, uint32_t);
|
||||
int fadvise(int, uint64_t, uint64_t, int);
|
||||
int fchdir(int);
|
||||
int fchmod(int, uint32_t) nothrow;
|
||||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
@@ -117,6 +117,8 @@ int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
int getdomainname(char *, size_t);
|
||||
int gethostname(char *, size_t);
|
||||
int getpgid(int);
|
||||
int getpid(void);
|
||||
int getppid(void);
|
||||
int getpriority(int, unsigned);
|
||||
int getrlimit(int, struct rlimit *);
|
||||
@@ -130,6 +132,7 @@ int madvise(void *, uint64_t, int);
|
||||
int mkdir(const char *, uint32_t);
|
||||
int mkdirat(int, const char *, uint32_t);
|
||||
int mkfifo(const char *, uint32_t);
|
||||
int mkfifoat(int, const char *, uint32_t);
|
||||
int mknod(const char *, uint32_t, uint64_t);
|
||||
int mknodat(int, const char *, int32_t, uint64_t);
|
||||
int mlock(const void *, size_t);
|
||||
@@ -138,8 +141,8 @@ int mlockall(int);
|
||||
int munlock(const void *, size_t);
|
||||
int munlockall(void);
|
||||
int nice(int);
|
||||
int open(const char *, int, ...) nodiscard;
|
||||
int openanon(char *, unsigned) nodiscard;
|
||||
int open(const char *, int, ...);
|
||||
int openanon(char *, unsigned);
|
||||
int openat(int, const char *, int, ...);
|
||||
int pause(void);
|
||||
int personality(uint64_t);
|
||||
@@ -147,8 +150,10 @@ int pipe(int[hasatleast 2]);
|
||||
int pipe2(int[hasatleast 2], int);
|
||||
int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||
int posix_madvise(void *, uint64_t, int);
|
||||
int prctl();
|
||||
int raise(int);
|
||||
int readlink(const char *, char *, size_t);
|
||||
int reboot(int);
|
||||
int remove(const char *);
|
||||
int rename(const char *, const char *);
|
||||
int renameat(int, const char *, int, const char *);
|
||||
@@ -172,12 +177,14 @@ int setuid(uint32_t);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
int sigignore(int);
|
||||
int sigprocmask(int, const struct sigset *, struct sigset *);
|
||||
int sigqueue(int, int, const union sigval);
|
||||
int sigsuspend(const struct sigset *);
|
||||
int stat(const char *, struct stat *);
|
||||
int symlink(const char *, const char *);
|
||||
int symlinkat(const char *, int, const char *);
|
||||
int sync_file_range(int, int64_t, int64_t, unsigned);
|
||||
int sysinfo(struct sysinfo *) paramsnonnull();
|
||||
int sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int sysinfo(struct sysinfo *);
|
||||
int touch(const char *, uint32_t);
|
||||
int truncate(const char *, uint64_t);
|
||||
int ttyname_r(int, char *, size_t);
|
||||
@@ -190,21 +197,20 @@ int wait(int *);
|
||||
int wait3(int *, int, struct rusage *);
|
||||
int wait4(int, int *, int, struct rusage *);
|
||||
int waitpid(int, int *, int);
|
||||
ssize_t lseek(int, int64_t, unsigned);
|
||||
ssize_t pread(int, void *, size_t, int64_t);
|
||||
ssize_t preadv(int, struct iovec *, int, int64_t);
|
||||
ssize_t pwrite(int, const void *, size_t, int64_t);
|
||||
ssize_t pwritev(int, const struct iovec *, int, int64_t);
|
||||
intptr_t syscall(int, ...);
|
||||
void sync(void);
|
||||
long ptrace(int, int, void *, void *);
|
||||
long telldir(DIR *);
|
||||
int getpid(void);
|
||||
long times(struct tms *);
|
||||
sighandler_t signal(int, sighandler_t);
|
||||
size_t GetFileSize(const char *);
|
||||
size_t getfiledescriptorsize(int);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t lseek(int, int64_t, unsigned);
|
||||
ssize_t pread(int, void *, size_t, int64_t);
|
||||
ssize_t preadv(int, struct iovec *, int, int64_t);
|
||||
ssize_t pwrite(int, const void *, size_t, int64_t);
|
||||
ssize_t pwritev(int, const struct iovec *, int, int64_t);
|
||||
ssize_t read(int, void *, size_t);
|
||||
ssize_t readansi(int, char *, size_t);
|
||||
ssize_t readlinkat(int, const char *, char *, size_t);
|
||||
@@ -220,11 +226,8 @@ uint32_t getsid(int) nosideeffect;
|
||||
uint32_t gettid(void) nosideeffect;
|
||||
uint32_t getuid(void) nosideeffect;
|
||||
uint32_t umask(int32_t);
|
||||
long ptrace(int, int, void *, void *);
|
||||
int chroot(const char *);
|
||||
int prctl();
|
||||
int sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int fchdir(int);
|
||||
void rewinddir(DIR *);
|
||||
void sync(void);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » formatting ─╬─│┼
|
||||
|
||||
+9
-4
@@ -41,8 +41,11 @@ LIBC_CALLS_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_POWERPROF \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV_CALLS \
|
||||
@@ -64,10 +67,6 @@ o/$(MODE)/libc/calls/raise.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/calls/siggy.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
-ffunction-sections
|
||||
|
||||
o/$(MODE)/libc/calls/sigenter-freebsd.o \
|
||||
o/$(MODE)/libc/calls/sigenter-netbsd.o \
|
||||
o/$(MODE)/libc/calls/sigenter-openbsd.o \
|
||||
@@ -85,6 +84,12 @@ o/$(MODE)/libc/calls/mkntenvblock.o: \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
o/$(MODE)/libc/calls/ioctl-siocgifconf.o \
|
||||
o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
||||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
uint32_t cfgetispeed(const struct termios *t) {
|
||||
if (CBAUD) {
|
||||
return t->c_cflag & CBAUD;
|
||||
} else {
|
||||
return t->c_ispeed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
uint32_t cfgetospeed(const struct termios *t) {
|
||||
if (CBAUD) {
|
||||
return t->c_cflag & CBAUD;
|
||||
} else {
|
||||
return t->c_ospeed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
void cfmakeraw(struct termios *t) {
|
||||
t->c_iflag &=
|
||||
~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
t->c_oflag &= ~OPOST;
|
||||
t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
t->c_cflag &= ~(CSIZE | PARENB);
|
||||
t->c_cflag |= CS8;
|
||||
t->c_cc[VMIN] = 1;
|
||||
t->c_cc[VTIME] = 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int cfsetispeed(struct termios *t, int speed) {
|
||||
if (speed) {
|
||||
if (CBAUD) {
|
||||
if (speed & ~CBAUD) return einval();
|
||||
t->c_cflag &= ~CBAUD;
|
||||
t->c_cflag |= speed;
|
||||
} else {
|
||||
t->c_ispeed = speed;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int cfsetospeed(struct termios *t, int speed) {
|
||||
if (CBAUD) {
|
||||
if (!(speed & ~CBAUD)) {
|
||||
t->c_cflag &= ~CBAUD;
|
||||
t->c_cflag |= speed;
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
t->c_ospeed = speed;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes permissions on file, e.g.:
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes owner and/or group of pathname.
|
||||
|
||||
@@ -30,14 +30,10 @@
|
||||
* time. Among the more popular is CLOCK_MONOTONIC. This function has a
|
||||
* zero syscall implementation of that on modern x86.
|
||||
*
|
||||
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. noting
|
||||
* that on Linux CLOCK_MONOTONIC is redefined to use the monotonic
|
||||
* clock that's actually monotonic lool
|
||||
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc.
|
||||
* @param ts is where the result is stored
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error ENOSYS if clockid isn't available; in which case this function
|
||||
* guarantees an ordinary timestamp is still stored to ts; and
|
||||
* errno isn't restored to its original value, to detect prec. loss
|
||||
* @error EINVAL if clockid isn't supported on this system
|
||||
* @see strftime(), gettimeofday()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
@@ -46,6 +42,7 @@ int clock_gettime(int clockid, struct timespec *ts) {
|
||||
axdx_t ad;
|
||||
struct NtFileTime ft;
|
||||
if (!ts) return efault();
|
||||
if (clockid == -1) return einval();
|
||||
if (!IsWindows()) {
|
||||
if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) {
|
||||
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
|
||||
|
||||
@@ -26,8 +26,9 @@ static bool AccessCommand(char path[hasatleast PATH_MAX], const char *name,
|
||||
size_t namelen, size_t pathlen) {
|
||||
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] =
|
||||
!IsWindows() ? '/' : memchr(path, '\\', pathlen) ? '\\' : '/';
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
}
|
||||
memcpy(path + pathlen, name, namelen + 1);
|
||||
@@ -93,7 +94,9 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
(AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf))) ||
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, ".") - pathbuf))) ||
|
||||
SearchPath(pathbuf, name, namelen)) {
|
||||
errno = olderr;
|
||||
return pathbuf;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/reverse.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
||||
static const char kPipeNamePrefix[] = "\\\\?\\pipe\\cosmo\\";
|
||||
|
||||
static textwindows size_t UintToChar16Array(char16_t *a, uint64_t i) {
|
||||
size_t j = 0;
|
||||
do {
|
||||
a[j++] = i % 10 + '0';
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
a[j] = 0;
|
||||
reverse(a, j);
|
||||
return j;
|
||||
}
|
||||
|
||||
textwindows char16_t *CreatePipeName(char16_t *a) {
|
||||
static long x;
|
||||
unsigned i;
|
||||
for (i = 0; kPipeNamePrefix[i]; ++i) a[i] = kPipeNamePrefix[i];
|
||||
i += UintToChar16Array(a + i, GetCurrentProcessId());
|
||||
a[i++] = u'-';
|
||||
i += UintToChar16Array(a + i, GetCurrentProcessId());
|
||||
a[i++] = u'-';
|
||||
i += UintToChar16Array(a + i, x++);
|
||||
a[i] = u'\0';
|
||||
return a;
|
||||
}
|
||||
+133
-28
@@ -16,47 +16,152 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fcntl_nt(int fd, int cmd, unsigned arg) {
|
||||
static textwindows int sys_fcntl_nt_reservefd(int start) {
|
||||
int fd;
|
||||
for (;;) {
|
||||
fd = start;
|
||||
if (fd >= g_fds.n) {
|
||||
if (__ensurefds(fd) == -1) return -1;
|
||||
}
|
||||
cmpxchg(&g_fds.f, fd, fd + 1);
|
||||
if (cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_dupfd(int oldfd, int cmd, int start) {
|
||||
int newfd;
|
||||
int64_t proc;
|
||||
if ((newfd = sys_fcntl_nt_reservefd(start)) != -1) {
|
||||
proc = GetCurrentProcess();
|
||||
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc,
|
||||
&g_fds.p[newfd].handle, 0, true,
|
||||
kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
|
||||
return newfd;
|
||||
} else {
|
||||
__releasefd(newfd);
|
||||
return __winerr();
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
||||
struct flock *l;
|
||||
uint32_t flags, err;
|
||||
struct NtOverlapped ov;
|
||||
int64_t pos, off, len, size;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!GetFileInformationByHandle(f->handle, &info)) return __winerr();
|
||||
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) return __winerr();
|
||||
l = (struct flock *)arg;
|
||||
len = l->l_len;
|
||||
off = l->l_start;
|
||||
size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow;
|
||||
switch (l->l_whence) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
off = pos + off;
|
||||
break;
|
||||
case SEEK_END:
|
||||
off = size - off;
|
||||
break;
|
||||
default:
|
||||
return einval();
|
||||
}
|
||||
if (!len) len = size - off;
|
||||
if (off < 0 || len < 0) return einval();
|
||||
offset2overlap(off, &ov);
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
|
||||
/* TODO: How can we make SQLite locks on Windows to work? */
|
||||
/* if (l->l_type == F_WRLCK) flags |= kNtLockfileExclusiveLock; */
|
||||
if (LockFileEx(f->handle, flags, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorLockViolation) err = EAGAIN;
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
} else if (l->l_type == F_UNLCK) {
|
||||
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorNotLocked) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
||||
uint32_t flags;
|
||||
if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdSocket)) {
|
||||
switch (cmd) {
|
||||
case F_GETFL:
|
||||
return g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
|
||||
O_NOATIME | O_NONBLOCK);
|
||||
case F_SETFL:
|
||||
/*
|
||||
* - O_APPEND doesn't appear to be tunable at cursory glance
|
||||
* - O_NONBLOCK might require we start doing all i/o in threads
|
||||
* - O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
|
||||
*/
|
||||
return einval();
|
||||
case F_GETFD:
|
||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||
return FD_CLOEXEC;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case F_SETFD:
|
||||
if (arg & FD_CLOEXEC) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
return FD_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return einval();
|
||||
if (cmd == F_GETFL) {
|
||||
return g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
|
||||
O_NOATIME | O_NONBLOCK);
|
||||
} else if (cmd == F_SETFL) {
|
||||
/*
|
||||
* - O_APPEND doesn't appear to be tunable at cursory glance
|
||||
* - O_NONBLOCK might require we start doing all i/o in threads
|
||||
* - O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
|
||||
*/
|
||||
return einval();
|
||||
} else if (cmd == F_GETFD) {
|
||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||
return FD_CLOEXEC;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (cmd == F_SETFD) {
|
||||
if (arg & FD_CLOEXEC) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
return FD_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
return 0;
|
||||
}
|
||||
} else if (cmd == F_SETLK || cmd == F_SETLKW) {
|
||||
return sys_fcntl_nt_lock(g_fds.p + fd, cmd, arg);
|
||||
} else if (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC) {
|
||||
return sys_fcntl_nt_dupfd(fd, cmd, arg);
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
return ebadf();
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
|
||||
int sys_fcntl(int fd, int cmd, uintptr_t arg) {
|
||||
int rc;
|
||||
bool islock;
|
||||
islock = cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK;
|
||||
if (islock) cosmo2flock(arg);
|
||||
rc = __sys_fcntl(fd, cmd, arg);
|
||||
if (islock) flock2cosmo(arg);
|
||||
return rc;
|
||||
}
|
||||
+11
-2
@@ -25,6 +25,15 @@
|
||||
*
|
||||
* CHECK_NE(-1, fcntl(fd, F_SETFD, FD_CLOEXEC));
|
||||
*
|
||||
* This function implements POSIX Advisory Locks, e.g.
|
||||
*
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));
|
||||
* // ...
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLK, &(struct flock){F_UNLCK}));
|
||||
*
|
||||
* Please be warned that locks currently do nothing on Windows since
|
||||
* figuring out how to polyfill them correctly is a work in progress.
|
||||
*
|
||||
* @param cmd can be F_{GET,SET}{FD,FL}, etc.
|
||||
* @param arg can be FD_CLOEXEC, etc. depending
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
@@ -32,9 +41,9 @@
|
||||
*/
|
||||
int fcntl(int fd, int cmd, ...) {
|
||||
va_list va;
|
||||
unsigned arg;
|
||||
uintptr_t arg;
|
||||
va_start(va, cmd);
|
||||
arg = va_arg(va, unsigned);
|
||||
arg = va_arg(va, uintptr_t);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_fcntl(fd, cmd, arg);
|
||||
|
||||
Loaded 100 of 6356 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user