diff --git a/Common/Std/libc.c b/Common/Std/libc.c index 3fd2b2d..a13f86c 100644 --- a/Common/Std/libc.c +++ b/Common/Std/libc.c @@ -1,8 +1,11 @@ #include "../std.h" +#include "../str.h" #include #include #include #include +#include +#include #include void *com_std_alloc(void *ptr, size_t size) { @@ -19,3 +22,50 @@ double com_std_sqrt(double v) { return sqrt(v); } double com_std_fabs(double v) { return fabs(v); } double com_std_sin(double v) { return sin(v); } double com_std_cos(double v) { return cos(v); } + +com_std_fd com_std_open(char *path, uint32_t flags) { + com_std_assert(flags != 0); + char *mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE ? "r+" + : flags & COM_STD_OPEN_READ ? "r" + : "w"; + return fopen(path, mode); +} + +bool com_std_write(com_std_fd fd, char *data, uint32_t bytes) { + com_std_assert(fd != NULL && data != NULL && bytes != 0); + bool s = fwrite(data, 1, bytes, fd) == bytes; + fflush(fd); + return s; +} + +int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { + com_std_assert(fd != NULL && data != NULL && upto != 0); + return fread(data, 1, upto, fd); +} + +bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { + com_std_assert(fd != NULL && bytes != 0); + return fseek(fd, bytes, SEEK_CUR) == 0; +} + +com_std_fd com_std_socket(bool isnetwork) { + if (!isnetwork) { + int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + return fdopen(sockfd, "w+b"); + } else + return NULL; +} + +bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) { + com_std_assert(address != NULL); + if (!isnetwork) { + struct sockaddr_un addr = {.sun_family = AF_UNIX}; + __builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address)); + return connect(fileno(fd), (struct sockaddr *)&addr, sizeof(addr)) == 0; + } else + return NULL; +} + +void com_std_exit(uint32_t status) { exit(status); } + +void com_std_close(com_std_fd fd) { fclose(fd); } diff --git a/Common/Std/linux-amd64.c b/Common/Std/linux-amd64.c new file mode 100644 index 0000000..cd5fc43 --- /dev/null +++ b/Common/Std/linux-amd64.c @@ -0,0 +1,93 @@ +/* + AMD64 specific Linux std parts. +*/ + +#include "linux.c" + +#include "../std.h" +#include +#include +#include +#include +#include + +inline com_std_fd com_std_open(char *path, uint32_t flags) { + com_std_assert(flags != 0); + uint32_t mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE + ? O_RDWR + : flags & COM_STD_OPEN_READ ? O_RDONLY + : O_WRONLY; + long ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(2), "D"(path), "S"(mode) + : "rcx", "r11", "memory"); + if (ret <= 0) /* Mark NULL, removing error code */ + ret = 0; + return (void *)ret; +} + +inline bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) { + long ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(1), "D"(fd), "S"(data), "d"(bytes) + : "rcx", "r11", "memory"); + return ret == bytes; +} + +inline int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { + long ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(0), "D"(fd), "S"(data), "d"(upto) + : "rcx", "r11", "memory"); + return ret; +} + +inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { + long ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(8), "D"(fd), "S"(bytes), "d"(SEEK_CUR) + : "rcx", "r11", "memory"); + return ret >= 0; /* TODO: Check whether offset is bytes offset exactly? */ +} + +inline com_std_fd com_std_socket(bool isnetwork) { + if (!isnetwork) { + int32_t sockfd; + __asm__ volatile("syscall" + : "=a"(sockfd) + : "a"(41), "D"(AF_UNIX), "S"(SOCK_STREAM), "d"(0) + : "rcx", "r11", "memory"); + if (sockfd < 0) + sockfd = 0; + return (void *)(int64_t)sockfd; + } else + return NULL; +} + +inline bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) { + com_std_assert(address != NULL); + if (!isnetwork) { + struct sockaddr_un addr = {.sun_family = AF_UNIX}; + __builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address)); + int32_t ret; + __asm__ volatile("syscall" + : "=a"(ret) + : "a"(42), "D"(fd), "S"(&addr), "d"(sizeof addr) + : "rcx", "r11", "memory"); + return ret == 0; + } else + return NULL; +} + +inline void com_std_exit(uint32_t status) { + __asm__ volatile("syscall" : : "a"(60), "D"(status) : "rcx", "r11", "memory"); + __builtin_unreachable(); +} + +inline void com_std_close(com_std_fd fd) { + __asm__ volatile("syscall" : : "a"(3), "D"(fd) : "rcx", "r11", "memory"); +} diff --git a/Common/Std/linux.c b/Common/Std/linux.c index 07777d5..e49ef29 100644 --- a/Common/Std/linux.c +++ b/Common/Std/linux.c @@ -1,3 +1,7 @@ +/* + Generic linux std parts. +*/ + #include "../def.h" #include "../std.h" #include "../str.h" @@ -8,18 +12,18 @@ void *com_std_alloc(void *ptr, size_t size) { return NULL; } void com_std_assert(bool holds) { /* TODO: Write line info to stderr as well. */ if (!holds) - com_std_syscall(__NR_exit, -1, 0, 0); + com_std_exit(-1); } /* TODO: Figure out a way to make it easy to deal with. */ void com_std_printf(char const *fmt, ...) { - com_std_syscall(1, 1, (intptr_t)fmt, com_str_ext_len(fmt)); + com_std_write((void *)1, fmt, com_str_ext_len(fmt)); } void com_std_print_str(char const *str, uint32_t len, bool newline) { - com_std_syscall(1, 1, (intptr_t)str, len); + com_std_write((void *)1, str, len); if (newline) - com_std_syscall(1, 1, (intptr_t)"\n", 1); + com_std_write((void *)1, "\n", 1); } double com_std_sqrt(double v) { return __builtin_sqrt(v); } diff --git a/Common/Std/stub.c b/Common/Std/stub.c index 55b156f..9020ac7 100644 --- a/Common/Std/stub.c +++ b/Common/Std/stub.c @@ -1,5 +1,8 @@ #include "../std.h" +#include +#include + void *com_std_alloc(void *ptr, size_t size) { return NULL; } void com_std_assert(bool holds) {} void com_std_printf(char const *fmt, ...) {} @@ -15,6 +18,24 @@ double com_std_sin(double v) { return 0; } double com_std_cos(double v) { return 0; } #endif +com_std_fd com_std_open(char *path, uint32_t flags) { return NULL; } +bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) { + return false; +} +int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { return -1; } +bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { return false; } +com_std_fd com_std_socket(bool isnetwork) { return NULL; } +bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) { + return false; +} +void com_std_exit(uint32_t status) { + __builtin_trap(); + while (1) { + } + __builtin_unreachable(); +} +void com_std_close(com_std_fd fd) { return; } + // void memcpy(void *__restrict dest, const void *__restrict src, size_t n) { // __builtin_memcpy(dest, src, n); // }; diff --git a/Common/bin.h b/Common/bin.h index 7461865..3327b58 100644 --- a/Common/bin.h +++ b/Common/bin.h @@ -14,7 +14,7 @@ #define COM_BIN_NAT_ENDIAN (1 << 2) typedef struct com_bin_interface { - /* Attempts to read exactly N bytes, returns false if it cannot. */ + /* Attempts to read exactly N bytes, return false if it cannot. */ bool (*readn)(void *ctx, char *into, uint32_t bytes); bool (*skipn)(void *ctx, uint32_t bytes); } com_bin_interface; diff --git a/Common/std.h b/Common/std.h index 93556fa..95da2bf 100644 --- a/Common/std.h +++ b/Common/std.h @@ -10,21 +10,21 @@ #include #include -#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX -#include - -static inline long com_std_syscall(long number, long arg1, long arg2, - long arg3) { - long ret; - __asm__ volatile("syscall" - : "=a"(ret) - : "a"(number), "D"(arg1), "S"(arg2), "d"(arg3) - : "rcx", "r11", "memory"); - return ret; -} -#endif +/* Generic system interface, linux/bsd derived. */ +typedef void *com_std_fd; +#define COM_STD_OPEN_READ (1 << 0) +#define COM_STD_OPEN_WRITE (1 << 1) +com_std_fd com_std_open(char *path, uint32_t flags); +bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes); +int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto); +bool com_std_sfwd(com_std_fd fd, uint32_t bytes); +com_std_fd com_std_socket(bool isnetwork); +bool com_std_connect(com_std_fd sock, bool isnetwork, char *address); +void com_std_exit(uint32_t status) __attribute__((noreturn)); +void com_std_close(com_std_fd fd); /* TODO: Remove, use buffer semantics instead. */ +/* Instead have a mmap functions here. */ /* Note: Freeing is done by passing 0 size to pointer. */ void *com_std_alloc(void *ptr, size_t size); diff --git a/Player/Display/x11.c b/Player/Display/x11.c index 95b1203..b8d992c 100644 --- a/Player/Display/x11.c +++ b/Player/Display/x11.c @@ -24,12 +24,12 @@ bool quited = false; bool fileread(void *ctx, char *into, uint32_t bytes) { - return com_std_syscall(0, (intptr_t)ctx, (intptr_t)into, bytes) == bytes; + return com_std_read(ctx, into, bytes) == bytes; } -bool fileskip(void *ctx, uint32_t bytes) { - return com_std_syscall(8, (intptr_t)ctx, bytes, 1) >= 0; -} +bool fileskip(void *ctx, uint32_t bytes) { return com_std_sfwd(ctx, bytes); } + +#define AUTH_ENTRY_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1" static struct plr_x11_auth_entry { uint16_t family; @@ -39,10 +39,8 @@ static struct plr_x11_auth_entry { } plr_x11_read_auth_entry(struct com_bin *b, struct com_buf *buf) { struct plr_x11_auth_entry result = {0}; - if (!com_bin_read_u16(b, &result.family)) { - com_std_printf("Failure to initialize X11\n"); + if (!com_bin_read_u16(b, &result.family)) goto BREAK; - } uint16_t addres_len; if (!com_bin_read_u16(b, &addres_len)) goto BREAK; @@ -75,6 +73,24 @@ BREAK: return result; } +static bool plr_x11_handshake(struct plr_x11_auth_entry auth_entry) { + struct { + uint8_t endianness; + uint8_t pad0; + uint16_t major_version; + uint16_t minor_version; + uint16_t auth_len; + uint16_t auth_data_len; + uint16_t pad1; + } __attribute__((packed)) request = { + .endianness = 'l', + .major_version = 11, + .auth_len = sizeof(AUTH_ENTRY_MAGIC_COOKIE) - 1, // IS -1 NEEDED? + .auth_data_len = auth_entry.auth_data->len, + }; + return true; +} + // TODO: correct error handling. extern int plr_display_x11_main(int argc, char *argv[]) { char test_string[] = "what is this?"; @@ -106,15 +122,13 @@ extern int plr_display_x11_main(int argc, char *argv[]) { /* TODO: Move init to separate func. */ /* Open X11 socket for communication. */ - int const xfd = com_std_syscall(41, AF_UNIX, SOCK_STREAM, 0); - if (xfd < 0) { + com_std_fd const xfd = com_std_socket(false); + if (!xfd) { com_std_printf("Failure to initialize X11\n"); return -1; } - struct sockaddr_un const addr = {.sun_family = AF_UNIX, - .sun_path = "/tmp/.X11-unix/X0"}; - if (com_std_syscall(42, xfd, (intptr_t)&addr, sizeof addr)) { + if (!com_std_connect(xfd, false, "/tmp/.X11-unix/X0")) { com_std_printf("Failure to initialize X11\n"); return -1; } @@ -131,7 +145,7 @@ extern int plr_display_x11_main(int argc, char *argv[]) { } /* Open it and parse. */ - int const xauthfd = com_std_syscall(2, (intptr_t)xauthpath, O_RDONLY, 0); + com_std_fd const xauthfd = com_std_open(xauthpath, COM_STD_OPEN_READ); if (xauthfd < 0) { com_std_printf("Failure to initialize X11\n"); return -1; @@ -143,13 +157,21 @@ extern int plr_display_x11_main(int argc, char *argv[]) { .flags = COM_BIN_BIG_ENDIAN, .interface = {.readn = fileread, .skipn = fileskip}}; - struct plr_x11_auth_entry auth_entry = - plr_x11_read_auth_entry(&xauthbin, xauthbuf); + /* Loop over auth entries until we find magic cookie one. */ + struct plr_x11_auth_entry auth_entry; + do { + com_buf_clear(xauthbuf); + auth_entry = plr_x11_read_auth_entry(&xauthbin, xauthbuf); + } while (auth_entry.success && auth_entry.family != 256); + if (!auth_entry.success) { + com_std_printf("Failure to initialize X11\n"); + return -1; + } - com_std_print_str(auth_entry.auth_name->data, auth_entry.auth_name->len, - true); - com_std_print_str(auth_entry.auth_data->data, auth_entry.auth_data->len, - true); + com_std_close(xauthfd); + + /* TODO: Check for auth_entry.name == MAGIC ? */ + plr_x11_handshake(auth_entry); com_buf_free(xauthbuf); diff --git a/Player/Makefile b/Player/Makefile index 114304f..71ca6a6 100644 --- a/Player/Makefile +++ b/Player/Makefile @@ -1,8 +1,8 @@ CC = clang RELEASE ?= 0 # Optimize. -DEBUG ?= 1 # Emit debug info. +DEBUG ?= 1 # Emit debug info. SQUEEZE ?= 0 # Nuclear option to save space. -BITS ?= 64 +BITS ?= 64 CFLAGS = -Wall -std=gnu99 -flto=thin -ffast-math -fno-ident -fvisibility=hidden ifeq ($(MAKECMDGOALS),linux) ifeq ($(RELEASE), 1) @@ -59,6 +59,7 @@ wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128 -mbulk-memory wasm: $(CC) -o player.wasm $(WASM) $(CFLAGS) +# TODO: Use https://github.com/amindlost/pmodew dos: $(DOS) $(DEPS) wcl386 -bt=dos4g -ox -l=dos4g $(DOS) diff --git a/Player/amalgam.c b/Player/amalgam.c index c4a04ef..65d0217 100644 --- a/Player/amalgam.c +++ b/Player/amalgam.c @@ -12,7 +12,7 @@ #include "./draw.c" #if COM_DEF_TARGET == COM_DEF_TARGET_LINUX -#include "../Common/Std/linux.c" +#include "../Common/Std/linux-amd64.c" #include "../Common/Timer/stub.c" #include "./Display/x11.c" #include "./Main/linux.c"