├── .gitignore ├── LICENSE ├── Makefile ├── PORTING.md ├── README.md ├── source ├── include │ ├── alloca.h │ ├── assert.h │ ├── ctype.h │ ├── elf.h │ ├── errno.h │ ├── fcntl.h │ ├── inttypes.h │ ├── math.h │ ├── pthread.h │ ├── pwd.h │ ├── sched.h │ ├── setjmp.h │ ├── signal.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── stropts.h │ ├── sys │ │ ├── stat.h │ │ ├── time.h │ │ └── times.h │ ├── termios.h │ ├── time.h │ ├── unistd.h │ └── wchar.h ├── libc │ ├── ctype.c │ ├── errno.c │ ├── fcntl.c │ ├── init.c │ ├── inttypes.c │ ├── pthread.c │ ├── pwd.c │ ├── setjmp.c │ ├── stdio │ │ ├── file.c │ │ └── printf.c │ ├── stdlib │ │ ├── environment.c │ │ ├── exit.c │ │ ├── memory.c │ │ ├── misc.c │ │ └── sort.c │ ├── string │ │ ├── cstring.c │ │ └── mem.c │ ├── time.c │ └── unistd │ │ ├── brk.c │ │ ├── dup.c │ │ ├── exec.c │ │ ├── sleep.c │ │ └── tty.c ├── libm │ └── math.c └── ports │ ├── i686-echidnaos │ ├── crt0.S │ ├── siglist.c │ ├── sys.c │ ├── sys │ │ ├── api.h │ │ ├── errnoval.h │ │ ├── fcntlval.h │ │ ├── ioctlval.h │ │ ├── signalval.h │ │ ├── statval.h │ │ ├── termiosval.h │ │ ├── timesval.h │ │ ├── timeval.h │ │ └── types.h │ └── sysdeps.c │ ├── x86_64-linux │ ├── crt0.S │ ├── siglist.c │ ├── sys │ │ ├── errnoval.h │ │ ├── fcntlval.h │ │ ├── ioctlval.h │ │ ├── signalval.h │ │ ├── statval.h │ │ ├── termiosval.h │ │ ├── timesval.h │ │ ├── timeval.h │ │ └── types.h │ └── sysdeps.c │ └── x86_64-qword │ ├── crt0.S │ ├── siglist.c │ ├── sys │ ├── errnoval.h │ ├── fcntlval.h │ ├── ioctlval.h │ ├── signalval.h │ ├── statval.h │ ├── termiosval.h │ ├── timesval.h │ ├── timeval.h │ └── types.h │ └── sysdeps.c └── test └── libc.c /.gitignore: -------------------------------------------------------------------------------- 1 | /**/*.o 2 | /**/*.a 3 | /**/*.so 4 | libctest 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Locations and targets. 2 | TARGET = x86_64-linux 3 | PREFIX = /usr/local 4 | DESTDIR = 5 | SRCDIR := source 6 | INCDIR := source/include 7 | TSTDIR := test 8 | PRTDIR := source/ports/$(TARGET) 9 | 10 | # Compilers and its flags. 11 | CC = cc 12 | AS = cc 13 | AR = ar 14 | CFLAGS = -Wall -Wextra -Wpedantic -g 15 | ASFLAGS = 16 | ARFLAGS = 17 | 18 | CHARDFLAGS := $(CFLAGS) -ffreestanding -I$(INCDIR) -I$(PRTDIR) 19 | ASHARDFLAGS := $(ASFLAGS) -ffreestanding 20 | ARHARDFLAGS := $(ARFLAGS) rcs 21 | 22 | # Source to compile. 23 | LIBCSRC := $(shell find $(SRCDIR)/libc -name '*.c') 24 | MATHSRC := $(shell find $(SRCDIR)/libm -name '*.c') 25 | PORTSRC := $(shell find $(PRTDIR) -name '*.c') 26 | CRT0SRC := $(PRTDIR)/crt0.S 27 | 28 | LIBCO := $(LIBCSRC:.c=.o) $(PORTSRC:.c=.o) 29 | MATHO := $(MATHSRC:.c=.o) 30 | 31 | CRT0 := crt0.o 32 | LIBC := libc.a 33 | MATH := libm.a 34 | 35 | .PHONY: all install-headers install test clean 36 | 37 | all: $(CRT0) $(LIBC) $(MATH) 38 | 39 | $(CRT0): $(CRT0SRC) 40 | $(AS) $(ASHARDFLAGS) -c $< -o $@ 41 | 42 | $(LIBC): $(LIBCO) 43 | $(AR) $(ARHARDFLAGS) $@ $(LIBCO) 44 | 45 | $(MATH): $(MATHO) 46 | $(AR) $(ARHARDFLAGS) $@ $(MATHO) 47 | 48 | %.o: %.c 49 | $(CC) $(CHARDFLAGS) -c $< -o $@ 50 | 51 | install-headers: 52 | install -d "$(DESTDIR)$(PREFIX)/include/sys" 53 | cp -rL $(INCDIR)/* "$(DESTDIR)$(PREFIX)/include" 54 | cp -rL $(PRTDIR)/sys/* "$(DESTDIR)$(PREFIX)/include/sys" 55 | 56 | install: install-headers all 57 | install -d "$(DESTDIR)$(PREFIX)/lib" 58 | install -m 644 crt0.o "$(DESTDIR)$(PREFIX)/lib/" 59 | install -m 644 libc.a "$(DESTDIR)$(PREFIX)/lib/" 60 | install -m 644 libm.a "$(DESTDIR)$(PREFIX)/lib/" 61 | 62 | test: all 63 | echo "Testing libc..." 64 | $(CC) -g -Wall -ffreestanding -nostdlib -nostartfiles -static $(TSTDIR)/libc.c crt0.o libc.a -I$(INCDIR) -I$(PRTDIR) -o libctest 65 | ./libctest 66 | rm -rf libctest 67 | 68 | clean: 69 | rm -f $(CRT0) $(LIBC) $(MATH) $(LIBCO) $(MATHO) 70 | -------------------------------------------------------------------------------- /PORTING.md: -------------------------------------------------------------------------------- 1 | # Porting slibc 2 | 3 | To get the changes on tree please make a pull request, I can mantain and 4 | update them from there if needed. 5 | 6 | The ports to slibc are located in [source/ports], there, each port targets both 7 | an architecture and OS, for example, `aarch64-linux`. This target can be chosen 8 | for compilation with the `TARGET` Makefile variable. 9 | 10 | There, in the chosen folder under [source/ports] a few items must be defined. 11 | 12 | # Items to define 13 | 14 | Given that we are trying to port to `X-Y`, this are the items needed for a port 15 | and their locations: 16 | 17 | - `crt0.S` under `source/ports/X-Y/crt0.S`, which sets up arguments to call 18 | the `__slibc_init` symbol, with the signature 19 | `void __slibc_init(int argc, char *argv[], char *envp[])`. 20 | - A series of C files implementing all the required functions, which are: 21 | - POSIX-compatible `fcntl`. 22 | - POSIX-compatible `open`. 23 | - POSIX-compatible `close`. 24 | - POSIX-compatible `read`. 25 | - POSIX-compatible `write`. 26 | - POSIX-compatible `rmdir`. 27 | - POSIX-compatible `unlink`. 28 | - POSIX-compatible `getcwd`. 29 | - POSIX-compatible `fork`. 30 | - POSIX-compatible `_exit`. 31 | - POSIX-compatible `lseek`. 32 | - POSIX-compatible `sbrk`. 33 | - POSIX-compatible `stat`. 34 | - POSIX-compatible `fstat`. 35 | - POSIX-compatible `clock_gettime`. 36 | - POSIX-compatible `sched_yield`. 37 | - POSIX-compatible `access`. 38 | - POSIX-compatible `pipe`. 39 | - POSIX-compatible `getpid`. 40 | - POSIX-compatible `getppid`. 41 | - POSIX-compatible `getpgrp`. 42 | - POSIX-compatible `getgid`. 43 | - POSIX-compatible `setgid`. 44 | - POSIX-compatible `getegid`. 45 | - POSIX-compatible `getuid`. 46 | - POSIX-compatible `setuid`. 47 | - POSIX-compatible `geteuid`. 48 | - POSIX-compatible `execve`. 49 | - POSIX-compatible `nanosleep`. 50 | - POSIX-compatible `ttyname_r`. 51 | - POSIX-compatible `alarm`. 52 | - POSIX-compatible `kill`. 53 | - POSIX-compatible `ioctl`. 54 | - POSIX-compatible `tcgetattr`. 55 | - POSIX-compatible `tcsetattr`. 56 | - POSIX-compatible `tcflow`. 57 | - POSIX-compatible `fchmod`. 58 | - POSIX-compatible `times`. 59 | - All the desired optional functions. 60 | - A declaration of `sys_siglist` and `sys_nsig`. 61 | 62 | The functions being syscalls or not does not matter as long as they express 63 | POSIX behaviour, this could be used to emulate POSIX behaviour on a non-POSIX 64 | syscall interface, for example. 65 | 66 | - A `sys` directory under `source/ports/X-Y/sys`, which will be installed 67 | verbatim with the final instalation under `sys`, containing: 68 | - The definition of the `errnoval.h`, `fcntlval.h`, `timeval.h`, `statval.h` 69 | `signalval.h`, `termiosval.h`, `timesval.h` and `ioctlval.h` headers, which 70 | define values taken by several functions that are by nature OS dependent. 71 | - The `types` header, since the types and values are part of the OS ABI. 72 | - Any desired optional headers. for optional declarations or values. 73 | 74 | For a more practical example, the `x86_64-linux` is a complete documented 75 | port that can be used as reference. 76 | 77 | # Expected environment 78 | 79 | A few conditions are expected by the libc for its inner workings: 80 | 81 | - File descriptors `0`, `1` and `2` must be already opened as they will serve as 82 | `stdin`, `stdout` and `stderr` respectively. 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slibc, the streaks libc 2 | 3 | A POSIX-compatible libc meant for ease of porting and performance for hobbyist 4 | OSes, obtaining this by clean abstractions and elegant C code. 5 | 6 | # Porting 7 | 8 | To learn about porting slibc to a new OS or architecture please refer to 9 | [this document](PORTING.md). 10 | 11 | # Building 12 | 13 | A simple makefile is provided, featuring a `PREFIX` and `DESTDIR` variables 14 | for choosing a path for installation. 15 | 16 | Only a C toolchain able to compile and link C and ASM and GNU Make are needed 17 | for compiling the project. 18 | 19 | An example process would be: 20 | 21 | ```bash 22 | make CFLAGS="-O2 -pipe" # Optimization flags are not passed by default. 23 | make test # Run the automated tests. 24 | make PREFIX="/usr/" install # Install, feel free to use PREFIX or DESTDIR. 25 | ``` 26 | -------------------------------------------------------------------------------- /source/include/alloca.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALLOCA_H__ 2 | #define __ALLOCA_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define alloca __builtin_alloca 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /source/include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASSERT_H__ 2 | #define __ASSERT_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define stringify(a) str(a) 12 | #define str(a) #a 13 | 14 | #ifdef NDEBUG 15 | #define assert(expr) ((void)0) 16 | #else 17 | #define assert(expr) do { \ 18 | if (!(expr)) { \ 19 | puts("Assertion failed at line " stringify(__LINE__) " of file " stringify(__FILE__)); \ 20 | exit(1); \ 21 | } \ 22 | } while (0) 23 | #endif 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /source/include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef CTYPE_H 2 | #define CTYPE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int isalnum(int c); 9 | int isalpha(int c); 10 | int isblank(int c); 11 | int iscntrl(int c); 12 | int isdigit(int c); 13 | int isgraph(int c); 14 | int islower(int c); 15 | int isprint(int c); 16 | int ispunct(int c); 17 | int isspace(int c); 18 | int isupper(int c); 19 | int isxdigit(int c); 20 | int tolower(int c); 21 | int toupper(int c); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/include/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef __ELF_H__ 2 | #define __ELF_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // Shamelesly copied from mlibc 11 | // https://github.com/managarm/mlibc/blob/master/options/elf/include/elf.h 12 | // Sucks to use MIT! 13 | 14 | // TODO: Convert the enums to #defines so that they work with #ifdef. 15 | 16 | #define ELFCLASS64 2 17 | #define ELFDATA2LSB 1 18 | #define ELFOSABI_SYSV 0 19 | #define EM_X86_64 62 20 | 21 | #define SHT_NULL 0 22 | #define SHT_PROGBITS 1 23 | #define SHT_SYMTAB 2 24 | #define SHT_STRTAB 3 25 | #define SHT_RELA 4 26 | #define SHT_HASH 5 27 | #define SHT_DYNAMIC 6 28 | #define SHT_NOBITS 8 29 | #define SHT_DYNSYM 11 30 | 31 | #define SHF_WRITE 1 32 | #define SHF_ALLOC 2 33 | #define SHF_EXECINSTR 4 34 | 35 | typedef uint64_t Elf64_Addr; 36 | typedef uint64_t Elf64_Off; 37 | typedef uint16_t Elf64_Half; 38 | typedef uint32_t Elf64_Word; 39 | typedef int32_t Elf64_Sword; 40 | typedef uint64_t Elf64_Xword; 41 | typedef int64_t Elf64_Sxword; 42 | 43 | typedef uint32_t Elf32_Addr; 44 | typedef uint32_t Elf32_Off; 45 | typedef uint16_t Elf32_Half; 46 | typedef uint32_t Elf32_Word; 47 | typedef int32_t Elf32_Sword; 48 | typedef uint64_t Elf32_Xword; 49 | typedef int64_t Elf32_Sxword; 50 | 51 | #define EI_NIDENT (16) 52 | 53 | typedef struct { 54 | unsigned char e_ident[EI_NIDENT]; /* ELF identification */ 55 | Elf32_Half e_type; /* Object file type */ 56 | Elf32_Half e_machine; /* Machine type */ 57 | Elf32_Word e_version; /* Object file version */ 58 | Elf32_Addr e_entry; /* Entry point address */ 59 | Elf32_Off e_phoff; /* Program header offset */ 60 | Elf32_Off e_shoff; /* Section header offset */ 61 | Elf32_Word e_flags; /* Processor-specific flags */ 62 | Elf32_Half e_ehsize; /* ELF header size */ 63 | Elf32_Half e_phentsize; /* Size of program header entry */ 64 | Elf32_Half e_phnum; /* Number of program header entries */ 65 | Elf32_Half e_shentsize; /* Size of section header entry */ 66 | Elf32_Half e_shnum; /* Number of section header entries */ 67 | Elf32_Half e_shstrndx; /* Section name string table index */ 68 | } Elf32_Ehdr; 69 | 70 | typedef struct { 71 | unsigned char e_ident[EI_NIDENT]; /* ELF identification */ 72 | Elf64_Half e_type; /* Object file type */ 73 | Elf64_Half e_machine; /* Machine type */ 74 | Elf64_Word e_version; /* Object file version */ 75 | Elf64_Addr e_entry; /* Entry point address */ 76 | Elf64_Off e_phoff; /* Program header offset */ 77 | Elf64_Off e_shoff; /* Section header offset */ 78 | Elf64_Word e_flags; /* Processor-specific flags */ 79 | Elf64_Half e_ehsize; /* ELF header size */ 80 | Elf64_Half e_phentsize; /* Size of program header entry */ 81 | Elf64_Half e_phnum; /* Number of program header entries */ 82 | Elf64_Half e_shentsize; /* Size of section header entry */ 83 | Elf64_Half e_shnum; /* Number of section header entries */ 84 | Elf64_Half e_shstrndx; /* Section name string table index */ 85 | } Elf64_Ehdr; 86 | 87 | enum { 88 | ET_NONE = 0, 89 | ET_REL = 1, 90 | ET_EXEC = 2, 91 | ET_DYN = 3, 92 | ET_CORE = 4, 93 | }; 94 | 95 | enum { 96 | SHN_UNDEF = 0, 97 | SHN_ABS = 0xFFF1 98 | }; 99 | 100 | typedef struct { 101 | Elf64_Word st_name; 102 | unsigned char st_info; 103 | unsigned char st_other; 104 | Elf64_Half st_shndx; 105 | Elf64_Addr st_value; 106 | Elf64_Xword st_size; 107 | } Elf64_Sym ; 108 | 109 | extern inline unsigned char ELF64_ST_BIND(unsigned char info) { 110 | return info >> 4; 111 | } 112 | extern inline unsigned char ELF64_ST_TYPE(unsigned char info) { 113 | return info & 0x0F; 114 | } 115 | extern inline unsigned char ELF64_ST_INFO(unsigned char bind, unsigned char type) { 116 | return (bind << 4) | type; 117 | } 118 | 119 | enum { 120 | STB_GLOBAL = 1, 121 | STB_WEAK = 2, 122 | STB_GNU_UNIQUE = 10 123 | }; 124 | 125 | enum { 126 | STT_OBJECT = 1, 127 | STT_FUNC = 2, 128 | STT_TLS = 6 129 | }; 130 | 131 | enum { 132 | R_X86_64_64 = 1, 133 | R_X86_64_COPY = 5, 134 | R_X86_64_GLOB_DAT = 6, 135 | R_X86_64_JUMP_SLOT = 7, 136 | R_X86_64_RELATIVE = 8, 137 | R_X86_64_DTPMOD64 = 16, 138 | R_X86_64_DTPOFF64 = 17, 139 | R_X86_64_TPOFF64 = 18, 140 | }; 141 | 142 | typedef struct { 143 | Elf64_Addr r_offset; 144 | uint64_t r_info; 145 | } Elf64_Rel; 146 | 147 | typedef struct { 148 | Elf64_Addr r_offset; 149 | Elf64_Xword r_info; 150 | Elf64_Sxword r_addend; 151 | } Elf64_Rela; 152 | 153 | static inline Elf64_Xword ELF64_R_SYM(Elf64_Xword info) { 154 | return info >> 32; 155 | } 156 | static inline Elf64_Xword ELF64_R_TYPE(Elf64_Xword info) { 157 | return info & 0xFFFFFFFF; 158 | } 159 | 160 | enum { 161 | PT_LOAD = 1, 162 | PT_DYNAMIC = 2, 163 | PT_INTERP = 3, 164 | PT_NOTE = 4, 165 | PT_PHDR = 6, 166 | PT_TLS = 7, 167 | PT_GNU_EH_FRAME = 0x6474E550, 168 | PT_GNU_STACK = 0x6474E551, 169 | PT_GNU_RELRO = 0x6474E552 170 | }; 171 | 172 | enum { 173 | PF_X = 1, 174 | PF_W = 2, 175 | PF_R = 4 176 | }; 177 | 178 | typedef struct { 179 | Elf64_Word p_type; /* Type of segment */ 180 | Elf64_Word p_flags; /* Segment attributes */ 181 | Elf64_Off p_offset; /* Offset in file */ 182 | Elf64_Addr p_vaddr; /* Virtual address in memory */ 183 | Elf64_Addr p_paddr; /* Reserved */ 184 | Elf64_Xword p_filesz; /* Size of segment in file */ 185 | Elf64_Xword p_memsz; /* Size of segment in memory */ 186 | Elf64_Xword p_align; /* Alignment of segment */ 187 | } Elf64_Phdr; 188 | 189 | enum { 190 | DT_NULL = 0, 191 | DT_NEEDED = 1, 192 | DT_PLTRELSZ = 2, 193 | DT_PLTGOT = 3, 194 | DT_HASH = 4, 195 | DT_STRTAB = 5, 196 | DT_SYMTAB = 6, 197 | DT_RELA = 7, 198 | DT_RELASZ = 8, 199 | DT_RELAENT = 9, 200 | DT_STRSZ = 10, 201 | DT_SYMENT = 11, 202 | DT_INIT = 12, 203 | DT_FINI = 13, 204 | DT_SONAME = 14, 205 | DT_RPATH = 15, 206 | DT_SYMBOLIC = 16, 207 | DT_REL = 17, 208 | DT_BIND_NOW = 24, 209 | DT_INIT_ARRAY = 25, 210 | DT_FINI_ARRAY = 26, 211 | DT_INIT_ARRAYSZ = 27, 212 | DT_FINI_ARRAYSZ = 28, 213 | DT_RUNPATH = 29, 214 | DT_PLTREL = 20, 215 | DT_DEBUG = 21, 216 | DT_JMPREL = 23, 217 | DT_FLAGS = 30, 218 | DT_GNU_HASH = 0x6ffffef5, 219 | DT_VERSYM = 0x6ffffff0, 220 | DT_RELACOUNT = 0x6ffffff9, 221 | DT_FLAGS_1 = 0x6ffffffb, 222 | DT_VERDEF = 0x6ffffffc, 223 | DT_VERDEFNUM = 0x6ffffffd, 224 | DT_VERNEED = 0x6ffffffe, 225 | DT_VERNEEDNUM = 0x6fffffff 226 | }; 227 | 228 | enum { 229 | // For DT_FLAGS. 230 | DF_SYMBOLIC = 0x02, 231 | DF_STATIC_TLS = 0x10, 232 | 233 | // For DT_FLAGS_1. 234 | DF_1_NOW = 0x00000001 235 | }; 236 | 237 | typedef struct { 238 | Elf32_Sword d_tag; 239 | union { 240 | Elf32_Word d_val; 241 | Elf32_Addr d_ptr; 242 | } d_un; 243 | } Elf32_Dyn; 244 | 245 | typedef struct { 246 | Elf64_Sxword d_tag; 247 | union { 248 | Elf64_Xword d_val; 249 | Elf64_Addr d_ptr; 250 | } d_un; 251 | } Elf64_Dyn; 252 | 253 | typedef struct { 254 | Elf32_Word sh_name; 255 | Elf32_Word sh_type; 256 | Elf32_Word sh_flags; 257 | Elf32_Addr sh_addr; 258 | Elf32_Off sh_offset; 259 | Elf32_Word sh_size; 260 | Elf32_Word sh_link; 261 | Elf32_Word sh_info; 262 | Elf32_Word sh_addralign; 263 | Elf32_Word sh_entsize; 264 | } Elf32_Shdr; 265 | 266 | typedef struct { 267 | Elf64_Word sh_name; 268 | Elf64_Word sh_type; 269 | Elf64_Xword sh_flags; 270 | Elf64_Addr sh_addr; 271 | Elf64_Off sh_offset; 272 | Elf64_Xword sh_size; 273 | Elf64_Word sh_link; 274 | Elf64_Word sh_info; 275 | Elf64_Xword sh_addralign; 276 | Elf64_Xword sh_entsize; 277 | } Elf64_Shdr; 278 | 279 | /* ST_TYPE (subfield of st_info) values (symbol type) */ 280 | #define STT_NOTYPE 0 281 | #define STT_OBJECT 1 282 | #define STT_FUNC 2 283 | #define STT_SECTION 3 284 | #define STT_FILE 4 285 | 286 | /* ST_BIND (subfield of st_info) values (symbol binding) */ 287 | #define STB_LOCAL 0 288 | #define STB_GLOBAL 1 289 | #define STB_WEAK 2 290 | 291 | /* sh_type (section type) values */ 292 | #define SHT_NULL 0 293 | #define SHT_PROGBITS 1 294 | #define SHT_SYMTAB 2 295 | #define SHT_STRTAB 3 296 | #define SHT_RELA 4 297 | #define SHT_NOBITS 8 298 | #define SHT_REL 9 299 | #define SHT_INIT_ARRAY 14 300 | #define SHT_FINI_ARRAY 15 301 | #define SHT_SYMTAB_SHNDX 18 302 | 303 | /* special section indices */ 304 | #define SHN_UNDEF 0 305 | #define SHN_LORESERVE 0xff00 306 | #define SHN_COMMON 0xfff2 307 | #define SHN_XINDEX 0xffff 308 | #define SHN_HIRESERVE 0xff00 309 | 310 | /* values for e_machine */ 311 | #define EM_NONE 0 312 | #define EM_SPARC 2 313 | #define EM_386 3 314 | #define EM_PPC 20 315 | #define EM_PPC64 21 316 | #define EM_X86_64 62 317 | 318 | /* e_indent constants */ 319 | #define EI_MAG0 0 320 | #define ELFMAG0 0x7f 321 | 322 | #define EI_MAG1 1 323 | #define ELFMAG1 'E' 324 | 325 | #define EI_MAG2 2 326 | #define ELFMAG2 'L' 327 | 328 | #define EI_MAG3 3 329 | #define ELFMAG3 'F' 330 | 331 | #define EI_CLASS 4 332 | #define ELFCLASSNONE 0 333 | #define ELFCLASS32 1 334 | #define ELFCLASS64 2 335 | #define ELFCLASSNUM 3 336 | 337 | #define EI_DATA 5 338 | #define ELFDATANONE 0 339 | #define ELFDATA2LSB 1 340 | #define ELFDATA2MSB 2 341 | #define ELFDATANUM 3 342 | 343 | #ifdef __cplusplus 344 | } 345 | #endif 346 | 347 | #endif 348 | -------------------------------------------------------------------------------- /source/include/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef __ERRNO_H__ 2 | #define __ERRNO_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // The inner value of the possible values of errno are dictated by the port 9 | // Following https://pubs.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html 10 | // for a basic implementation. 11 | #include 12 | 13 | // TODO: Make this thread-local. 14 | #define errno __errno 15 | extern int __errno; 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /source/include/fcntl.h: -------------------------------------------------------------------------------- 1 | #ifndef __FCNTL_H__ 2 | #define __FCNTL_H__ 3 | 4 | #include 5 | #include 6 | 7 | // The inner value of the possible values of oflags are dictated by the port 8 | // Following https://pubs.opengroup.org/onlinepubs/009695399/basedefs/fcntl.h.html 9 | // for a basic implementation. 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | int creat(const char *path, mode_t mode); 17 | int fcntl(int fd, int command, ...); // Defined by the port. 18 | int open(const char *path, int oflag, ...); // Defined by the port. 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /source/include/inttypes.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTTYPES_H__ 2 | #define __INTTYPES_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // TODO: Pretty sure these macros are self explanatory. 11 | #define PRIx64 "PLACEHOLDER PLEASE IMPLEMENT" 12 | #define PRId64 "PLACEHOLDER PLEASE IMPLEMENT" 13 | #define PRIu64 "PLACEHOLDER PLEASE IMPLEMENT" 14 | 15 | typedef struct { 16 | intmax_t quot; 17 | intmax_t rem; 18 | } imaxdiv_t; 19 | 20 | imaxdiv_t imaxdiv(intmax_t numerator, intmax_t denominator); 21 | intmax_t imaxabs(intmax_t number); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATH_H__ 2 | #define __MATH_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // Some constants. 9 | #define M_E 2.71828182845904523536 10 | #define M_LOG2E 1.44269504088896340736 11 | #define M_LOG10E 0.434294481903251827651 12 | #define M_LN2 0.693147180559945309417 13 | #define M_LN10 2.30258509299404568402 14 | #define M_PI 3.14159265358979323846 15 | #define M_PI_2 1.57079632679489661923 16 | #define M_PI_4 0.785398163397448309616 17 | #define M_1_PI 0.318309886183790671538 18 | #define M_2_PI 0.636619772367581343076 19 | #define M_2_SQRTPI 1.12837916709551257390 20 | #define M_SQRT2 1.41421356237309504880 21 | #define M_SQRT1_2 0.707106781186547524401 22 | 23 | int isnan(double x); 24 | double fmod(double x, double y); 25 | double sin(double rad); 26 | double cos(double rad); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /source/include/pthread.h: -------------------------------------------------------------------------------- 1 | #ifndef __PTHREAD_H__ 2 | #define __PTHREAD_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | typedef struct { 12 | int placeholder; 13 | } pthread_mutexattr_t; 14 | 15 | int pthread_mutexattr_init(pthread_mutexattr_t *attr); 16 | int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); 17 | int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type); 18 | int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); 19 | 20 | #define PTHREAD_MUTEX_INITIALIZER {0, {0}} 21 | #define PTHREAD_MUTEX_RECURSIVE 0 22 | 23 | typedef struct { 24 | int locked; 25 | pthread_mutexattr_t attr; 26 | } pthread_mutex_t; 27 | 28 | int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); 29 | int pthread_mutex_destroy(pthread_mutex_t *mutex); 30 | int pthread_mutex_lock(pthread_mutex_t *mutex); 31 | int pthread_mutex_trylock(pthread_mutex_t *mutex); 32 | int pthread_mutex_unlock(pthread_mutex_t *mutex); 33 | 34 | #define PTHREAD_ONCE_INIT {0} 35 | 36 | typedef struct { 37 | int placeholder; 38 | } pthread_once_t; 39 | 40 | int pthread_once(pthread_once_t *once, void (*init_routine)(void)); 41 | 42 | typedef struct { 43 | int placeholder; 44 | } pthread_condattr_t; 45 | 46 | typedef struct { 47 | int placeholder; 48 | } pthread_cond_t; 49 | 50 | int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); 51 | int pthread_cond_destroy(pthread_cond_t *cond); 52 | int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); 53 | int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); 54 | int pthread_cond_signal(pthread_cond_t *cond); 55 | int pthread_cond_broadcast(pthread_cond_t *cond); 56 | 57 | typedef struct { 58 | int placeholder; 59 | } pthread_attr_t; 60 | 61 | typedef struct { 62 | int placeholder; 63 | } pthread_t; 64 | 65 | int pthread_cancel(pthread_t thread); 66 | int pthread_detach(pthread_t thread); 67 | int pthread_equal(pthread_t thread1, pthread_t thread2); 68 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(entrypoint)(void *), void *arg); 69 | pthread_t pthread_self(void); 70 | int pthread_join(pthread_t thread, void **value_ptr); 71 | 72 | typedef struct { 73 | int placeholder; 74 | } pthread_key_t; 75 | 76 | int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); 77 | int pthread_key_delete(pthread_key_t key); 78 | int pthread_setspecific(pthread_key_t key, const void *specific); 79 | void *pthread_getspecific(pthread_key_t key); 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /source/include/pwd.h: -------------------------------------------------------------------------------- 1 | #ifndef __PWD_H__ 2 | #define __PWD_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | struct passwd { 11 | char *pw_name; // User's login name. 12 | uid_t pw_uid; // Numerical user ID. 13 | gid_t pw_gid; // Numerical group ID. 14 | char *pw_dir; // Initial working directory. 15 | char *pw_shell; // Program to use as shell. 16 | }; 17 | 18 | struct passwd *getpwnam(const char *name); 19 | struct passwd *getpwuid(uid_t uid); 20 | 21 | int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **); 22 | int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **); 23 | 24 | void endpwent(void); 25 | struct passwd *getpwent(void); 26 | void setpwent(void); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /source/include/sched.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCHED_H__ 2 | #define __SCHED_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int sched_yield(void); // Provided by the sysdeps. 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /source/include/setjmp.h: -------------------------------------------------------------------------------- 1 | #ifndef SETJMP_H 2 | #define SETJMP_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #ifdef __x86_64__ 11 | typedef uint64_t jmp_buf[8]; /// Non volatile GPRs. 12 | #elif __i386__ 13 | typedef uint32_t jmp_buf[6]; /// Non volatile GPRs. 14 | #else 15 | #error "Architecture not supported for setjmp" 16 | #endif 17 | 18 | void longjmp(jmp_buf state, int value); 19 | int setjmp(jmp_buf state); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /source/include/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIGNAL_H__ 2 | #define __SIGNAL_H__ 3 | 4 | #include // Kernel-specific signal info. 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef void (*__sighandler)(int); 12 | 13 | extern const int sys_nsig; // Defined by the port. 14 | extern const char *const sys_siglist[]; // Defined by the port. 15 | 16 | int kill(pid_t pid, int signal); // Defined by port. 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /source/include/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDINT_H__ 2 | #define __STDINT_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef __UINT8_TYPE__ uint8_t; 9 | typedef __UINT16_TYPE__ uint16_t; 10 | typedef __UINT32_TYPE__ uint32_t; 11 | typedef __UINT64_TYPE__ uint64_t; 12 | 13 | typedef __INT8_TYPE__ int8_t; 14 | typedef __INT16_TYPE__ int16_t; 15 | typedef __INT32_TYPE__ int32_t; 16 | typedef __INT64_TYPE__ int64_t; 17 | #define INT8_MAX __INT8_MAX 18 | #define INT16_MAX __INT16_MAX 19 | #define INT32_MAX __INT32_MAX 20 | #define INT64_MAX __INT64_MAX 21 | #define INT8_MIN (-__INT8_MAX - 1) 22 | #define INT16_MIN (-__INT16_MAX - 1) 23 | #define INT32_MIN (-__INT32_MAX - 1) 24 | #define INT64_MIN (-__INT64_MAX - 1) 25 | 26 | typedef __UINT8_TYPE__ uint_fast8_t; 27 | typedef __UINT32_TYPE__ uint_fast16_t; 28 | typedef __UINT32_TYPE__ uint_fast32_t; 29 | typedef __UINT64_TYPE__ uint_fast64_t; 30 | #define UINT_FAST8_MAX UINT8_MAX 31 | #define UINT_FAST16_MAX UINT64_MAX 32 | #define UINT_FAST32_MAX UINT64_MAX 33 | #define UINT_FAST64_MAX UINT64_MAX 34 | #define UINT_FAST8_MIN UINT8_MIN 35 | #define UINT_FAST16_MIN UINT64_MIN 36 | #define UINT_FAST32_MIN UINT64_MIN 37 | #define UINT_FAST64_MIN UINT64_MIN 38 | 39 | typedef __INT8_TYPE__ int_fast8_t; 40 | typedef __INT32_TYPE__ int_fast16_t; 41 | typedef __INT32_TYPE__ int_fast32_t; 42 | typedef __INT64_TYPE__ int_fast64_t; 43 | #define INT_FAST8_MAX INT8_MAX 44 | #define INT_FAST16_MAX INT32_MAX 45 | #define INT_FAST32_MAX INT32_MAX 46 | #define INT_FAST64_MAX INT64_MAX 47 | #define INT_FAST8_MIN INT8_MIN 48 | #define INT_FAST16_MIN INT32_MIN 49 | #define INT_FAST32_MIN INT32_MIN 50 | #define INT_FAST64_MIN INT64_MIN 51 | 52 | typedef __INTMAX_TYPE__ intmax_t; 53 | typedef __INTPTR_TYPE__ intptr_t; 54 | typedef __PTRDIFF_TYPE__ ptrdiff_t; 55 | #define INTMAX_MAX __INTMAX_MAX__ 56 | #define INTPTR_MAX __INTPTR_MAX__ 57 | #define PTRDIFF_MAX __PTRDIFF_MAX__ 58 | #define INTMAX_MIN (-__INTMAX_MAX__ - 1) 59 | #define INTPTR_MIN (-__INTPTR_MAX__ - 1) 60 | #define PTRDIFF_MIN (-__PTRDIFF_MAX__ - 1) 61 | 62 | typedef __UINTMAX_TYPE__ uintmax_t; 63 | typedef __UINTPTR_TYPE__ uintptr_t; 64 | typedef __SIZE_TYPE__ size_t; 65 | #define UINTMAX_MAX __UINTMAX_MAX__ 66 | #define UINTPTR_MAX __UINTPTR_MAX__ 67 | #define SIZE_MAX __SIZE_MAX__ 68 | 69 | #define WCHAR_MAX __WCHAR_MAX__ 70 | #define WCHAR_MIN __WCHAR_MIN__ 71 | 72 | #define WINT_MAX __WINT_MAX__ 73 | #define WINT_MIN __WINT_MIN__ 74 | 75 | #define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__ 76 | #define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__ 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /source/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDIO_H__ 2 | #define __STDIO_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #define getc fgetc 14 | #define putc fputc 15 | #define EOF (-1) 16 | 17 | #define FILE_BUFFER_SIZE 512 18 | 19 | typedef struct { 20 | int inner_fd; 21 | int is_readable; 22 | int is_writable; 23 | int is_eof; 24 | int is_error; 25 | size_t buffer_base; 26 | size_t bytes_in_buffer; 27 | size_t buffer_i; 28 | char buffer[FILE_BUFFER_SIZE]; 29 | } FILE; 30 | 31 | extern FILE *stdin; 32 | extern FILE *stdout; 33 | extern FILE *stderr; 34 | 35 | FILE *fdopen(int fd, const char *mode); 36 | FILE *fopen(const char *filename, const char *mode); 37 | int fclose(FILE *stream); 38 | int fputc(int character, FILE *stream); 39 | int fgetc(FILE *stream); 40 | int fflush(FILE *stream); 41 | int fseek(FILE *stream, long offset, int where); 42 | long ftell(FILE *stream); 43 | int fputs(const char *str, FILE *stream); 44 | char *fgets(char *result, int count, FILE *stream); 45 | size_t fwrite(const void *pointer, size_t size, size_t nitems, FILE *stream); 46 | size_t fread(void *pointer, size_t size, size_t nitems, FILE *stream); 47 | int feof(FILE *stream); 48 | int ferror(FILE *stream); 49 | void clearerr(FILE *stream); 50 | int fileno(FILE *stream); 51 | int putchar(int character); 52 | int getchar(void); 53 | int puts(const char *str); 54 | int remove(const char *pathname); 55 | int sscanf(const char *str, const char *format, ...); 56 | 57 | int printf(const char *format, ...); 58 | int vprintf(const char *format, va_list args); 59 | int fprintf(FILE *stream, const char *format, ...); 60 | int vfprintf(FILE *stream, const char *format, va_list args); 61 | int sprintf(char *result, const char *format, ...); 62 | int snprintf(char *result, size_t count, const char *format, ...); 63 | int vsprintf(char *result, const char *format, va_list args); 64 | int vsnprintf(char *result, size_t count, const char *format, va_list args); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /source/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDLIB_H__ 2 | #define __STDLIB_H__ 3 | 4 | #include 5 | 6 | #define EXIT_FAILURE 1 7 | #define EXIT_SUCCESS 0 8 | 9 | // TODO: Actually use locales for this. 10 | // #define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE]) 11 | // #define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1) 12 | #define MB_CUR_MAX 4 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | void abort(void); 19 | void exit(int status); 20 | void _Exit(int status); 21 | 22 | void *malloc(size_t size); 23 | void *calloc(size_t count, size_t size); 24 | void *realloc(void *pointer, size_t size); 25 | void free(void *pointer); 26 | 27 | char *getenv(const char *name); 28 | int atoi(const char *str); 29 | long strtol(const char *str, char **endptr, int base); 30 | 31 | void qsort(void *base, size_t count, size_t width, int (*compare)(const void *, const void *)); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /source/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef __STRING_H__ 2 | #define __STRING_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | size_t strlen(const char *str); 11 | int strcmp(const char *str1, const char *str2); 12 | int strncmp(const char *str1, const char *str2, size_t num); 13 | char *strcpy(char *destination, const char *source); 14 | char *strncpy(char *destination, const char *source, size_t count); 15 | char *strcat(char *destination, const char *source); 16 | char *strchr(const char *string, int c); 17 | char *strrchr(const char *string, int c); 18 | char *strstr(const char *string, const char *searched); 19 | char *strpbrk(const char *string, const char *searched); 20 | char *strsignal(int signal); 21 | 22 | void *memset(void *destination, int value, size_t count); 23 | void *memcpy(void *destination, const void *source, size_t count); 24 | int memcmp(const void *source1, const void *source2, size_t count); 25 | void *memmove(void *destination, const void *source, size_t count); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /source/include/stropts.h: -------------------------------------------------------------------------------- 1 | #ifndef __STROPTS_H__ 2 | #define __STROPTS_H__ 3 | 4 | #include // Kernel-specific ioctl values. 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int ioctl(int fd, int request, ...); // Port. 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /source/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__STAT_H__ 2 | #define __SYS__STAT_H__ 3 | 4 | #include // Kernel-specific stat values. 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | int stat(const char *path, struct stat *result); // Port. 12 | int fstat(int fd, struct stat *result); // Ditto. 13 | int fchmod(int fd, mode_t mode); // Ditto. 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /source/include/sys/time.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIME_H__ 2 | #define __SYS__TIME_H__ 3 | 4 | #include 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /source/include/sys/times.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMES_H__ 2 | #define __SYS__TIMES_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | clock_t times(struct tms *t); // Defined by port. 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /source/include/termios.h: -------------------------------------------------------------------------------- 1 | #ifndef __TERMIOS_H__ 2 | #define __TERMIOS_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int tcgetattr(int fd, struct termios *result); 11 | int tcsetattr(int fd, int action, const struct termios *result); 12 | int tcflow(int fd, int action); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /source/include/time.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIME_H__ 2 | #define __TIME_H__ 3 | 4 | #include 5 | #include 6 | 7 | // The structures and clockid kernel-specific macros used in this file 8 | // defined accordingly to 9 | // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | int clock_gettime(clockid_t clock_id, struct timespec *tp); // Implemented by the port. 17 | int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); // Ditto. 18 | time_t time(time_t *store); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /source/include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef __UNISTD_H__ 2 | #define __UNISTD_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define _POSIX_VERSION 200809L 11 | #define _POSIX2_VERSION 200809L 12 | #define _XOPEN_VERSION 700 13 | //#define _POSIX_THREADS 200809L 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | extern char **environ; 20 | 21 | int close(int fd); // Implemented by the port. 22 | ssize_t read(int fd, void *buf, size_t count); // Ditto. 23 | ssize_t write(int fd, const void *buf, size_t count); // Ditto. 24 | char *getcwd(char *buf, size_t size); // Ditto. 25 | int rmdir(const char *path); // Ditto. 26 | int unlink(const char *path); // Ditto. 27 | int fork(void); // Ditto. 28 | void _exit(int status); // Ditto. 29 | off_t lseek(int fd, off_t offset, int whence); // Ditto. 30 | void *sbrk(intptr_t increment); // Ditto. 31 | int access(const char *path, int amode); // Ditto. 32 | int pipe(int fds[2]); // Ditto. 33 | pid_t getpid(void); // Ditto. 34 | pid_t getppid(void); // Ditto. 35 | pid_t getpgrp(void); // Ditto. 36 | gid_t getgid(void); // Ditto. 37 | int setgid(gid_t gid); // Ditto. 38 | gid_t getegid(void); // Ditto. 39 | uid_t getuid(void); // Ditto. 40 | int setuid(uid_t uid); // Ditto. 41 | uid_t geteuid(void); // Ditto. 42 | unsigned alarm(unsigned seconds); // Ditto. 43 | int brk(void *address); 44 | 45 | int execl(const char *path, const char *arg0, ...); 46 | int execv(const char *path, char *const argv[]); 47 | int execle(const char *path, const char *arg0, ...); 48 | int execve(const char *path, char *const argv[], char *const envp[]); // Port. 49 | int execlp(const char *file, const char *arg0, ...); 50 | int execvp(const char *file, char *const argv[]); 51 | int execvpe(const char *file, char *const argv[], char *const envp[]); 52 | 53 | unsigned sleep(unsigned seconds); 54 | 55 | #define TTY_NAME_MAX 100 56 | 57 | int ttyname_r(int fd, char *name, size_t namesize); // Port. 58 | char *ttyname(int fd); 59 | 60 | int dup(int fd); 61 | int dup2(int fd, int fd2); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /source/include/wchar.h: -------------------------------------------------------------------------------- 1 | #ifndef __WCHAR_H__ 2 | #define __WCHAR_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include // For the actual wchar_t 9 | 10 | #define WCHAR_MIN __WCHAR_MIN__ 11 | #define WCHAR_MAX __WCHAR_MAX__ 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /source/libc/ctype.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int isalnum(int c) { 5 | return isalpha(c) || isdigit(c); 6 | } 7 | 8 | int isalpha(int c) { 9 | return islower(c) || isupper(c); 10 | } 11 | 12 | int isblank(int c) { 13 | return c == ' ' || c == '\t'; 14 | } 15 | 16 | int iscntrl(int c) { 17 | // According to standard ASCII character set, control characters are between 18 | // ASCII codes 0x00 (NUL), 0x1F (US), and 0x7F (DEL). 19 | return (c >= 0x00 && c <= 0x1F) || (c == 0x7F); 20 | } 21 | 22 | int isdigit(int c) { 23 | return c >= '0' && c <= '9'; 24 | } 25 | 26 | int isgraph(int c) { 27 | // TODO: This function checks whether the passed character has graphical 28 | // representation using locale, would be nice to make it do so. 29 | return isprint(c); 30 | } 31 | 32 | int islower(int c) { 33 | return c >= 'a' && c <= 'z'; 34 | } 35 | 36 | int isprint(int c) { 37 | return !iscntrl(c); 38 | } 39 | 40 | int ispunct(int c) { 41 | return isgraph(c) && !isalnum(c); 42 | } 43 | 44 | int isspace(int c) { 45 | return isblank(c) || c == '\n' || c == '\v' || c == '\f' || c == '\r'; 46 | } 47 | 48 | int isupper(int c) { 49 | return c >= 'A' && c <= 'Z'; 50 | } 51 | 52 | int isxdigit(int c) { 53 | return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 54 | } 55 | 56 | int tolower(int c) { 57 | return isupper(c) ? c - ('A' - 'a') : c; 58 | } 59 | 60 | int toupper(int c) { 61 | return islower(c) ? c - ('a' - 'A') : c; 62 | } 63 | -------------------------------------------------------------------------------- /source/libc/errno.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int __errno; 4 | -------------------------------------------------------------------------------- /source/libc/fcntl.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int creat(const char *path, mode_t mode) { 4 | return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); 5 | } 6 | -------------------------------------------------------------------------------- /source/libc/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern int main(int argc, char *argv[], char *envp[]); 6 | 7 | void __slibc_init(int argc, char *argv[], char *envp[]) { 8 | // Initialize std* buffers. 9 | stdin = fdopen(0, "r"); 10 | stdout = fdopen(1, "w"); 11 | stderr = fdopen(2, "w"); 12 | 13 | // Setup environ. 14 | environ = envp; 15 | 16 | // Call main and exit with its result. 17 | int exit_code = main(argc, argv, envp); 18 | exit(exit_code); 19 | } 20 | -------------------------------------------------------------------------------- /source/libc/inttypes.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | imaxdiv_t imaxdiv(intmax_t numerator, intmax_t denominator) { 4 | imaxdiv_t ret; 5 | 6 | ret.quot = numerator / denominator; 7 | ret.rem = numerator % denominator; 8 | if (numerator >= 0 && ret.rem < 0) { 9 | ret.quot++; 10 | ret.rem -= denominator; 11 | } 12 | 13 | return ret; 14 | } 15 | 16 | intmax_t imaxabs(intmax_t number) { 17 | return number > 0 ? number : -number; 18 | } 19 | -------------------------------------------------------------------------------- /source/libc/pthread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define LOCKED_VAL 1 6 | #define UNLOCKED_VAL 0 7 | 8 | int pthread_mutexattr_init(pthread_mutexattr_t *attr) { 9 | (void)attr; 10 | assert(!"Not implemented"); 11 | return 0; 12 | } 13 | 14 | int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { 15 | (void)attr; 16 | assert(!"Not implemented"); 17 | return 0; 18 | } 19 | 20 | int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) { 21 | (void)attr; 22 | (void)type; 23 | assert(!"Not implemented"); 24 | return 0; 25 | } 26 | 27 | int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { 28 | (void)attr; 29 | (void)type; 30 | assert(!"Not implemented"); 31 | return 0; 32 | } 33 | 34 | int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { 35 | mutex->locked = UNLOCKED_VAL; 36 | if (attr == NULL) { 37 | mutex->attr = (pthread_mutexattr_t){0}; 38 | } else { 39 | mutex->attr = *attr; 40 | } 41 | return 0; 42 | } 43 | 44 | int pthread_mutex_destroy(pthread_mutex_t *mutex) { 45 | (void)mutex; 46 | return 0; 47 | } 48 | 49 | int pthread_mutex_lock(pthread_mutex_t *mutex) { 50 | int expected = UNLOCKED_VAL; 51 | while (__atomic_compare_exchange_n(&mutex->locked, &expected, LOCKED_VAL, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED)); 52 | return 0; 53 | } 54 | 55 | int pthread_mutex_trylock(pthread_mutex_t *mutex) { 56 | int expected = UNLOCKED_VAL; 57 | return __atomic_compare_exchange_n(&mutex->locked, &expected, LOCKED_VAL, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); 58 | } 59 | 60 | int pthread_mutex_unlock(pthread_mutex_t *mutex) { 61 | int expected = UNLOCKED_VAL; 62 | __atomic_store(&mutex->locked, &expected, __ATOMIC_RELAXED); 63 | return 0; 64 | } 65 | 66 | int pthread_once(pthread_once_t *once, void (*init_routine)(void)) { 67 | (void)once; 68 | (void)init_routine; 69 | assert(!"Not implemented"); 70 | return 0; 71 | } 72 | 73 | int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { 74 | (void)cond; 75 | (void)attr; 76 | assert(!"Not implemented"); 77 | return 0; 78 | } 79 | 80 | int pthread_cond_destroy(pthread_cond_t *cond) { 81 | (void)cond; 82 | assert(!"Not implemented"); 83 | return 0; 84 | } 85 | 86 | int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { 87 | (void)cond; 88 | (void)mutex; 89 | assert(!"Not implemented"); 90 | return 0; 91 | } 92 | 93 | int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { 94 | (void)cond; 95 | (void)mutex; 96 | (void)abstime; 97 | assert(!"Not implemented"); 98 | return 0; 99 | } 100 | 101 | int pthread_cond_signal(pthread_cond_t *cond) { 102 | (void)cond; 103 | assert(!"Not implemented"); 104 | return 0; 105 | } 106 | 107 | int pthread_cond_broadcast(pthread_cond_t *cond) { 108 | (void)cond; 109 | assert(!"Not implemented"); 110 | return 0; 111 | } 112 | 113 | int pthread_cancel(pthread_t thread) { 114 | (void)thread; 115 | assert(!"Not implemented"); 116 | return 0; 117 | } 118 | 119 | int pthread_detach(pthread_t thread) { 120 | (void)thread; 121 | assert(!"Not implemented"); 122 | return 0; 123 | } 124 | 125 | int pthread_equal(pthread_t thread1, pthread_t thread2) { 126 | (void)thread1; 127 | (void)thread2; 128 | assert(!"Not implemented"); 129 | return 0; 130 | } 131 | 132 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(entrypoint)(void *), void *arg) { 133 | (void)thread; 134 | (void)attr; 135 | (void)entrypoint; 136 | (void)arg; 137 | assert(!"Not implemented"); 138 | return 0; 139 | } 140 | 141 | pthread_t pthread_self(void) { 142 | assert(!"Not implemented"); 143 | pthread_t thread = {0}; 144 | return thread; 145 | } 146 | 147 | int pthread_join(pthread_t thread, void **value_ptr) { 148 | (void)thread; 149 | (void)value_ptr; 150 | assert(!"Not implemented"); 151 | return 0; 152 | } 153 | 154 | int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { 155 | (void)key; 156 | (void)destructor; 157 | assert(!"Not implemented"); 158 | return 0; 159 | } 160 | 161 | int pthread_key_delete(pthread_key_t key) { 162 | (void)key; 163 | assert(!"Not implemented"); 164 | return 0; 165 | } 166 | 167 | int pthread_setspecific(pthread_key_t key, const void *specific) { 168 | (void)key; 169 | (void)specific; 170 | assert(!"Not implemented"); 171 | return 0; 172 | } 173 | 174 | void *pthread_getspecific(pthread_key_t key) { 175 | (void)key; 176 | assert(!"Not implemented"); 177 | return NULL; 178 | } 179 | -------------------------------------------------------------------------------- /source/libc/pwd.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // TODO: Implement (lol). 4 | -------------------------------------------------------------------------------- /source/libc/setjmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __x86_64__ 4 | __attribute__((naked)) void longjmp(jmp_buf state, int value) { 5 | (void)state; 6 | (void)value; 7 | asm volatile( 8 | "movq %rsi, %rax\n" 9 | "testq %rax, %rax\n" 10 | "setz %al\n" 11 | "movq 0(%rdi), %rbx\n" 12 | "movq 8(%rdi), %rbp\n" 13 | "movq 16(%rdi), %r12\n" 14 | "movq 24(%rdi), %r13\n" 15 | "movq 32(%rdi), %r14\n" 16 | "movq 40(%rdi), %r15\n" 17 | "movq 48(%rdi), %rsp\n" 18 | "jmp *56(%rdi)\n" 19 | ); 20 | } 21 | 22 | __attribute__((naked)) int setjmp(jmp_buf state) { 23 | (void)state; 24 | asm volatile( 25 | "movq %rbx, 0(%rdi)\n" 26 | "movq %rbp, 8(%rdi)\n" 27 | "movq %r12, 16(%rdi)\n" 28 | "movq %r13, 24(%rdi)\n" 29 | "movq %r14, 32(%rdi)\n" 30 | "movq %r15, 40(%rdi)\n" 31 | "leaq 8(%rsp), %rdx\n" 32 | "movq %rdx, 48(%rdi)\n" 33 | "movq (%rsp), %rdx\n" 34 | "movq %rdx, 56(%rdi)\n" 35 | "movq $0, %rax\n" 36 | "ret\n" 37 | ); 38 | } 39 | #elif __i386__ 40 | __attribute__((naked)) void longjmp(jmp_buf state, int value) { 41 | asm volatile(""); 42 | } 43 | 44 | __attribute__((naked)) int setjmp(jmp_buf state) { 45 | asm volatile(""); 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /source/libc/stdio/file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | FILE *stdin = NULL; 9 | FILE *stdout = NULL; 10 | FILE *stderr = NULL; 11 | 12 | static size_t file_count = 0; 13 | static FILE **file_list = NULL; 14 | 15 | FILE *fdopen(int fd, const char *mode) { 16 | (void)mode; 17 | FILE *ret = calloc(1, sizeof(FILE)); 18 | if (ret == NULL) { 19 | return NULL; 20 | } 21 | 22 | for (size_t i = 0; i < file_count; i++) { 23 | if (file_list[i] == NULL) { 24 | file_list[i] = ret; 25 | goto slot_found; 26 | } 27 | } 28 | 29 | size_t index = file_count; 30 | file_count = file_count == 0 ? 32 : file_count * 2; 31 | 32 | FILE **tmp = realloc(file_list, file_count * sizeof(FILE*)); 33 | if (tmp == NULL) { 34 | free(ret); 35 | return NULL; 36 | } 37 | file_list = tmp; 38 | file_list[index] = ret; 39 | for (size_t i = index + 1; i < file_count; i++) { 40 | file_list[i] = NULL; 41 | } 42 | 43 | slot_found:; 44 | size_t mode_len = strlen(mode); 45 | for (size_t i = 0; i < mode_len; i++) { 46 | switch (mode[i]) { 47 | case 'r': case '+': 48 | ret->is_readable = 1; 49 | break; 50 | case 'a': case 'w': 51 | ret->is_writable = 1; 52 | break; 53 | } 54 | } 55 | 56 | ret->inner_fd = fd; 57 | return ret; 58 | } 59 | 60 | FILE *fopen(const char *filename, const char *mode) { 61 | int flags; 62 | 63 | if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0) { 64 | flags = O_RDONLY; 65 | } else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) { 66 | flags = O_WRONLY | O_CREAT | O_TRUNC; 67 | } else if (strcmp(mode, "a") == 0 || strcmp(mode, "ab") == 0) { 68 | flags = O_WRONLY | O_CREAT | O_APPEND; 69 | } else if (strcmp(mode, "r+") == 0 || strcmp(mode, "rb+") == 0 || strcmp(mode, "r+b") == 0) { 70 | flags = O_RDWR; 71 | } else if (strcmp(mode, "w+") == 0 || strcmp(mode, "wb+") == 0 || strcmp(mode, "w+b") == 0) { 72 | flags = O_RDWR | O_CREAT | O_TRUNC; 73 | } else if (strcmp(mode, "a+") == 0 || strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) { 74 | flags = O_RDWR | O_CREAT | O_APPEND; 75 | } else { 76 | errno = EINVAL; 77 | return NULL; 78 | } 79 | 80 | int fd = open(filename, flags); 81 | if (fd == -1) { 82 | return NULL; 83 | } 84 | 85 | return fdopen(fd, mode); 86 | } 87 | 88 | int fclose(FILE *stream) { 89 | int ret = close(stream->inner_fd); 90 | for (size_t i = 0; i < file_count; i++) { 91 | if (stream == file_list[i]) { 92 | file_list[i] = NULL; 93 | } 94 | } 95 | 96 | free(stream); 97 | return ret; 98 | } 99 | 100 | int fputc(int character, FILE *stream) { 101 | stream->is_error = 0; 102 | stream->is_eof = 0; 103 | 104 | if (!stream->is_writable) { 105 | stream->is_error = 1; 106 | return EOF; 107 | } 108 | 109 | if (stream->buffer_i == stream->bytes_in_buffer) { 110 | stream->bytes_in_buffer++; 111 | } 112 | stream->buffer[stream->buffer_i++] = character; 113 | 114 | if (stream->buffer_i >= FILE_BUFFER_SIZE || character == '\n') { 115 | if (fflush(stream)) { 116 | return EOF; 117 | } 118 | off_t lseek_ret = lseek(stream->inner_fd, 0, SEEK_CUR); 119 | if (lseek_ret == (off_t)-1) { 120 | stream->buffer_base = 0; 121 | } else { 122 | stream->buffer_base = lseek_ret; 123 | } 124 | if (stream->is_readable) { 125 | int ret = read(stream->inner_fd, stream->buffer, FILE_BUFFER_SIZE); 126 | switch (ret) { 127 | case -1: 128 | stream->is_error = 1; 129 | return EOF; 130 | } 131 | stream->bytes_in_buffer = ret; 132 | } 133 | } 134 | 135 | return character; 136 | } 137 | 138 | int fgetc(FILE *stream) { 139 | stream->is_error = 0; 140 | stream->is_eof = 0; 141 | 142 | if (!stream->is_readable) { 143 | stream->is_error = 1; 144 | return EOF; 145 | } 146 | 147 | int ret = stream->buffer[stream->buffer_i++]; 148 | 149 | if (stream->buffer_i == stream->bytes_in_buffer) { 150 | if (fflush(stream)) { 151 | return EOF; 152 | } 153 | off_t lseek_ret = lseek(stream->inner_fd, 0, SEEK_CUR); 154 | if (lseek_ret == (off_t)-1) { 155 | stream->buffer_base = 0; 156 | } else { 157 | stream->buffer_base = lseek_ret; 158 | } 159 | int ret = read(stream->inner_fd, stream->buffer, FILE_BUFFER_SIZE); 160 | switch (ret) { 161 | case -1: 162 | stream->is_error = 1; 163 | return EOF; 164 | case 0: 165 | stream->is_eof = 1; 166 | return EOF; 167 | } 168 | stream->bytes_in_buffer = ret; 169 | } 170 | 171 | return ret; 172 | } 173 | 174 | int fflush(FILE *stream) { 175 | if (stream == NULL) { 176 | for (size_t i = 0; i < file_count; i++) { 177 | if (file_list[i] != NULL) { 178 | fflush(file_list[i]); 179 | } 180 | } 181 | return 0; 182 | } 183 | 184 | stream->is_error = 0; 185 | stream->is_eof = 0; 186 | 187 | if (stream->is_writable) { 188 | lseek(stream->inner_fd, stream->buffer_base, SEEK_SET); 189 | int ret = write(stream->inner_fd, stream->buffer, stream->buffer_i); 190 | 191 | stream->buffer_i = 0; 192 | stream->bytes_in_buffer = 0; 193 | 194 | if (ret == -1) { 195 | stream->is_error = 1; 196 | return EOF; 197 | } 198 | } else { 199 | lseek(stream->inner_fd, stream->buffer_base + stream->buffer_i, SEEK_SET); 200 | stream->buffer_i = 0; 201 | stream->bytes_in_buffer = 0; 202 | } 203 | 204 | return 0; 205 | } 206 | 207 | int fseek(FILE *stream, long offset, int where) { 208 | fflush(stream); 209 | off_t ret = lseek(stream->inner_fd, offset, where); 210 | if (ret == (off_t)-1) { 211 | return -1; 212 | } 213 | return 0; 214 | } 215 | 216 | long ftell(FILE *stream) { 217 | return stream->buffer_base + stream->buffer_i; 218 | } 219 | 220 | int fputs(const char *str, FILE *stream) { 221 | for (size_t i = 0; str[i] != '\0'; i++) { 222 | if (fputc(str[i], stream) == EOF) { 223 | return EOF; 224 | } 225 | } 226 | return 0; 227 | } 228 | 229 | char *fgets(char *result, int count, FILE *stream) { 230 | char *ret = result; 231 | int i; 232 | for (i = 0; i < count - 1; i++) { 233 | int c = fgetc(stream); 234 | if (c == EOF) { 235 | ret = NULL; 236 | break; 237 | } 238 | result[i] = c; 239 | if (c == '\n') { 240 | break; 241 | } 242 | } 243 | result[++i] = '\0'; 244 | return ret; 245 | } 246 | 247 | size_t fwrite(const void *pointer, size_t size, size_t nitems, FILE *stream) { 248 | size_t pointer_i = 0; 249 | const uint8_t *data = pointer; 250 | for (size_t i = 0; i < nitems; i++) { 251 | for (size_t j = 0; j < size; j++) { 252 | if (fputc(data[pointer_i++], stream) == EOF) { 253 | return i; 254 | } 255 | } 256 | } 257 | return nitems; 258 | } 259 | 260 | size_t fread(void *pointer, size_t size, size_t nitems, FILE *stream) { 261 | size_t pointer_i = 0; 262 | uint8_t *data = pointer; 263 | for (size_t i = 0; i < nitems; i++) { 264 | for (size_t j = 0; j < size; j++) { 265 | int c = fgetc(stream); 266 | if (c == EOF) { 267 | return i; 268 | } 269 | data[pointer_i++] = c; 270 | } 271 | } 272 | return nitems; 273 | } 274 | 275 | int feof(FILE *stream) { 276 | return stream->is_eof; 277 | } 278 | 279 | int ferror(FILE *stream) { 280 | return stream->is_error; 281 | } 282 | 283 | void clearerr(FILE *stream) { 284 | stream->is_eof = 0; 285 | stream->is_error = 1; 286 | } 287 | 288 | int fileno(FILE *stream) { 289 | return stream->inner_fd; 290 | } 291 | 292 | int putchar(int character) { 293 | return fputc(character, stdout); 294 | } 295 | 296 | int getchar(void) { 297 | return fgetc(stdin); 298 | } 299 | 300 | int puts(const char *str) { 301 | if (fputs(str, stdout) == EOF || fputc('\n', stdout) == EOF) { 302 | return EOF; 303 | } 304 | 305 | return 0; 306 | } 307 | 308 | int remove(const char *pathname) { 309 | int ret = unlink(pathname); 310 | return (ret && errno == EISDIR) ? rmdir(pathname) : ret; 311 | } 312 | 313 | // TODO: Put ourselves thru the pain and suffering of actually implementing 314 | // scanf. 315 | int sscanf(const char *str, const char *format, ...) { 316 | (void)str; 317 | (void)format; 318 | puts("sscanf is a stub"); 319 | exit(EXIT_FAILURE); 320 | return EOF; 321 | } 322 | -------------------------------------------------------------------------------- /source/libc/stdio/printf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int printf(const char *format, ...) { 10 | va_list args; 11 | va_start(args, format); 12 | int ret = vfprintf(stdout, format, args); 13 | va_end(args); 14 | return ret; 15 | } 16 | 17 | int vprintf(const char *format, va_list args) { 18 | return vfprintf(stdout, format, args); 19 | } 20 | 21 | int fprintf(FILE *stream, const char *format, ...) { 22 | va_list args; 23 | va_start(args, format); 24 | int ret = vfprintf(stream, format, args); 25 | va_end(args); 26 | return ret; 27 | } 28 | 29 | int vfprintf(FILE *stream, const char *format, va_list args) { 30 | char buffer[300]; 31 | int ret = vsnprintf(buffer, 300, format, args); 32 | fputs(buffer, stream); 33 | return ret; 34 | } 35 | 36 | int sprintf(char *result, const char *format, ...) { 37 | va_list args; 38 | va_start(args, format); 39 | int ret = vsnprintf(result, SIZE_MAX, format, args); 40 | va_end(args); 41 | return ret; 42 | } 43 | 44 | int snprintf(char *result, size_t count, const char *format, ...) { 45 | va_list args; 46 | va_start(args, format); 47 | int ret = vsnprintf(result, count, format, args); 48 | va_end(args); 49 | return ret; 50 | } 51 | 52 | int vsprintf(char *result, const char *format, va_list args) { 53 | return vsnprintf(result, SIZE_MAX, format, args); 54 | } 55 | 56 | /* 57 | * Everything below here has been stolen (allowed in on their license) and 58 | * lightly modified from lvlibc, function made by https://github.com/qookei. 59 | * Feel free to distribute it around, as it is a great self-contained snippet 60 | * of good stuff. 61 | */ 62 | #define FMT_PUT(dst, len, c) {\ 63 | if(!len) goto end;\ 64 | *(dst)++ = (c);\ 65 | len--;\ 66 | ret++;\ 67 | } 68 | 69 | static const char *digits_upper = "0123456789ABCDEF"; 70 | static const char *digits_lower = "0123456789abcdef"; 71 | 72 | static char *num_fmt(char *buf, size_t buf_len, uint64_t i, int base, int padding, char pad_with, int handle_signed, int upper, int len, char plus_char) { 73 | int neg = (int64_t)i < 0 && handle_signed; 74 | 75 | if (neg) 76 | i = (uint64_t)(-((int64_t)i)); 77 | 78 | char *ptr = buf + buf_len - 1; 79 | *ptr = '\0'; 80 | 81 | const char *digits = upper ? digits_upper : digits_lower; 82 | 83 | do { 84 | *--ptr = digits[i % base]; 85 | if (padding) 86 | padding--; 87 | if (len > 0) 88 | len--; 89 | buf_len--; 90 | } while ((i /= base) != 0 && (len == -1 || len) && buf_len); 91 | 92 | while (padding && buf_len) { 93 | *--ptr = pad_with; 94 | padding--; 95 | buf_len--; 96 | } 97 | 98 | if (!buf_len) 99 | return ptr; 100 | 101 | if (neg) 102 | *--ptr = '-'; 103 | 104 | if (!neg && plus_char) 105 | *--ptr = plus_char; 106 | 107 | return ptr; 108 | } 109 | 110 | #define NUM_BUF_LEN 48 111 | 112 | int vsnprintf(char *buf, size_t len, const char *fmt, va_list arg) { 113 | int ret = 0; 114 | uint64_t i; 115 | char *s; 116 | char num_buf[NUM_BUF_LEN]; 117 | 118 | while(*fmt && len) { 119 | if (*fmt != '%') { 120 | *buf++ = *fmt; 121 | fmt++; 122 | continue; 123 | } 124 | 125 | fmt++; 126 | int padding = 0; 127 | char pad_with = ' '; 128 | int wide = 0, upper = 0; 129 | char plus_char = 0; 130 | int alternative = 0; 131 | int precision = 0; 132 | 133 | if (*fmt == '0') { 134 | pad_with = '0'; 135 | fmt++; 136 | } else if (*fmt == '#') { 137 | alternative = 1; 138 | fmt++; 139 | } else if (*fmt == ' ') { 140 | plus_char = ' '; 141 | fmt++; 142 | } else if (*fmt == '+') { 143 | plus_char = '+'; 144 | fmt++; 145 | } else if (*fmt == '-') { 146 | // TODO: left align with padding 147 | fmt++; 148 | } 149 | 150 | if (*fmt == '*') { 151 | padding = va_arg(arg, int); 152 | fmt++; 153 | } else while (isdigit(*fmt)) { 154 | padding *= 10; 155 | padding += *fmt++ - '0'; 156 | } 157 | 158 | // next character is the precision 159 | if (*fmt == '.') { 160 | fmt++; 161 | if (*fmt == '*') { 162 | precision = va_arg(arg, int); 163 | fmt++; 164 | } else while (isdigit(*fmt)) { 165 | precision *= 10; 166 | precision += *fmt++ - '0'; 167 | } 168 | } else { 169 | precision = -1; 170 | } 171 | 172 | while (*fmt == 'l') { 173 | wide = 1; 174 | fmt++; 175 | } 176 | 177 | while (*fmt == 'h') { 178 | // XXX: handle narrower types in a special way? 179 | fmt++; 180 | } 181 | 182 | upper = *fmt == 'X' || *fmt == 'P'; 183 | 184 | switch (*fmt) { 185 | case 'c': { 186 | i = va_arg(arg, int); 187 | FMT_PUT(buf, len, i); 188 | break; 189 | } 190 | 191 | case 'i': 192 | case 'd': { 193 | if (wide) 194 | i = va_arg(arg, long int); 195 | else 196 | i = va_arg(arg, int); 197 | 198 | char *c = num_fmt(num_buf, NUM_BUF_LEN, i, 10, padding, pad_with, 1, 0, -1, plus_char); 199 | while (*c) { 200 | FMT_PUT(buf, len, *c); 201 | c++; 202 | } 203 | break; 204 | } 205 | 206 | case 'u': { 207 | if (wide) 208 | i = va_arg(arg, long int); 209 | else 210 | i = va_arg(arg, int) & 0xFFFFFFFFul; 211 | 212 | char *c = num_fmt(num_buf, NUM_BUF_LEN, i, 10, padding, pad_with, 0, 0, -1, plus_char); 213 | while (*c) { 214 | FMT_PUT(buf, len, *c); 215 | c++; 216 | } 217 | break; 218 | } 219 | 220 | case 'o': { 221 | if (wide) 222 | i = va_arg(arg, long int); 223 | else 224 | i = va_arg(arg, int); 225 | 226 | char *c = num_fmt(num_buf, NUM_BUF_LEN, i, 8, padding, pad_with, 0, 0, -1, plus_char); 227 | 228 | if (alternative) 229 | FMT_PUT(buf, len, '0'); 230 | 231 | while (*c) { 232 | FMT_PUT(buf, len, *c); 233 | c++; 234 | } 235 | break; 236 | } 237 | 238 | case 'X': 239 | case 'x': { 240 | if (wide) 241 | i = va_arg(arg, long int); 242 | else 243 | i = va_arg(arg, int); 244 | 245 | char *c = num_fmt(num_buf, NUM_BUF_LEN, i, 16, padding, pad_with, 0, upper, wide ? 16 : 8, plus_char); 246 | 247 | if (alternative) { 248 | FMT_PUT(buf, len, '0'); 249 | FMT_PUT(buf, len, upper ? 'X' : 'x'); 250 | } 251 | 252 | while (*c) { 253 | FMT_PUT(buf, len, *c); 254 | c++; 255 | } 256 | break; 257 | } 258 | 259 | case 'P': 260 | case 'p': { 261 | i = (uintptr_t)(va_arg(arg, void *)); 262 | 263 | char *c = num_fmt(num_buf, NUM_BUF_LEN, i, 16, padding, pad_with, 0, upper, sizeof(uintptr_t) / 4, plus_char); 264 | while (*c) { 265 | FMT_PUT(buf, len, *c); 266 | c++; 267 | } 268 | break; 269 | } 270 | 271 | case 's': { 272 | s = va_arg(arg, char *); 273 | while (*s && precision) { 274 | FMT_PUT(buf, len, *s); 275 | s++; 276 | if (precision > 0) 277 | precision--; 278 | } 279 | break; 280 | } 281 | 282 | case '%': { 283 | FMT_PUT(buf, len, '%'); 284 | break; 285 | } 286 | } 287 | 288 | fmt++; 289 | } 290 | 291 | end: 292 | if (len) 293 | *buf++ = '\0'; 294 | 295 | return ret; 296 | } 297 | -------------------------------------------------------------------------------- /source/libc/stdlib/environment.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char *getenv(const char *name) { 6 | size_t name_len = strlen(name); 7 | for (size_t i = 0; environ[i] != NULL; i++) { 8 | if (strncmp(name, environ[i], name_len) == 0) { 9 | // Assume vars have the format VAR=VALUE. 10 | return environ[i] + name_len + 1; 11 | } 12 | } 13 | 14 | return NULL; 15 | } 16 | -------------------------------------------------------------------------------- /source/libc/stdlib/exit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void abort(void) { 5 | _exit(EXIT_FAILURE); // DEATH DEATH DEATH DEATH. 6 | } 7 | 8 | void exit(int status) { 9 | // TODO: Call the finalizers, all that stuff. 10 | _exit(status); 11 | } 12 | 13 | void _Exit(int status) { 14 | exit(status); 15 | } 16 | -------------------------------------------------------------------------------- /source/libc/stdlib/memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BLOCK_SIZE 128 9 | #define INITIAL_POOL_SIZE 128 10 | 11 | struct malloc_metadata { 12 | size_t blocks; 13 | size_t size; 14 | char data[]; 15 | }; 16 | 17 | static void *bitmap = NULL; 18 | static size_t bitmap_last_index = 0; 19 | static uintptr_t heap_base = 0; 20 | static size_t pool_size = 0; 21 | static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER; 22 | 23 | #define SIZE_T_BITS (sizeof(size_t) * 8) 24 | #define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b)) 25 | 26 | static int bitmap_test(void *bitmap, size_t num) { 27 | size_t index = num / SIZE_T_BITS; 28 | size_t offset = num % SIZE_T_BITS; 29 | return ((size_t *)bitmap)[index] & ((size_t)1 << offset); 30 | } 31 | 32 | static void bitmap_set(void *bitmap, size_t num) { 33 | size_t index = num / SIZE_T_BITS; 34 | size_t offset = num % SIZE_T_BITS; 35 | ((size_t *)bitmap)[index] |= (size_t)1 << offset; 36 | } 37 | 38 | static void bitmap_unset(void *bitmap, size_t num) { 39 | size_t index = num / SIZE_T_BITS; 40 | size_t offset = num % SIZE_T_BITS; 41 | ((size_t *)bitmap)[index] &= ~((size_t)1 << offset); 42 | } 43 | 44 | static void *allocate_blocks_inner(size_t count, size_t limit) { 45 | size_t p = 0; 46 | 47 | while (bitmap_last_index < limit) { 48 | if (!bitmap_test(bitmap, bitmap_last_index++)) { 49 | if (++p == count) { 50 | size_t block = bitmap_last_index - count; 51 | for (size_t i = block; i < bitmap_last_index; i++) { 52 | bitmap_set(bitmap, i); 53 | } 54 | return (void *)(block * BLOCK_SIZE + heap_base); 55 | } 56 | } else { 57 | p = 0; 58 | } 59 | } 60 | 61 | return NULL; 62 | } 63 | 64 | static void *allocate_blocks(size_t count) { 65 | size_t last_used = bitmap_last_index; 66 | size_t bitmap_size = pool_size / 8; 67 | void *ret = allocate_blocks_inner(count, bitmap_size); 68 | if (ret == NULL) { 69 | bitmap_last_index = 0; 70 | ret = allocate_blocks_inner(count, last_used); 71 | } 72 | 73 | return ret; 74 | } 75 | 76 | static void *block_alloc(size_t block_count) { 77 | if (heap_base == 0) { 78 | heap_base = (uintptr_t)sbrk(0); 79 | } 80 | 81 | void *ret; 82 | while ((ret = allocate_blocks(block_count)) == NULL) { 83 | size_t old_bitmap_size = pool_size / 8; 84 | 85 | if (pool_size == 0) { 86 | pool_size = INITIAL_POOL_SIZE; 87 | } else { 88 | pool_size *= 2; 89 | } 90 | 91 | size_t new_bitmap_size = pool_size / 8; 92 | size_t new_heap_size = pool_size * BLOCK_SIZE + new_bitmap_size; 93 | void *new_bitmap = (void *)((heap_base + new_heap_size) - new_bitmap_size); 94 | 95 | if (brk((void *)(heap_base + new_heap_size)) != 0) { 96 | return NULL; 97 | } 98 | 99 | memset(new_bitmap, 0, new_bitmap_size); 100 | memcpy(new_bitmap, bitmap, old_bitmap_size); 101 | bitmap = new_bitmap; 102 | } 103 | 104 | return ret; 105 | } 106 | 107 | static void block_free(void *ptr, size_t count) { 108 | size_t block = ((size_t)ptr - heap_base) / BLOCK_SIZE; 109 | for (size_t i = 0; i < count; i++) { 110 | bitmap_unset(bitmap, block + i); 111 | } 112 | } 113 | 114 | void *malloc(size_t size) { 115 | pthread_mutex_lock(&alloc_mutex); 116 | size_t block_count = DIV_ROUNDUP(sizeof(struct malloc_metadata) + size, BLOCK_SIZE); 117 | struct malloc_metadata *ptr = block_alloc(block_count); 118 | if (ptr == NULL) { 119 | pthread_mutex_unlock(&alloc_mutex); 120 | return NULL; 121 | } 122 | 123 | ptr->blocks = block_count; 124 | ptr->size = size; 125 | 126 | pthread_mutex_unlock(&alloc_mutex); 127 | return ptr->data; 128 | } 129 | 130 | void *calloc(size_t count, size_t size) { 131 | void *ret = malloc(count * size); 132 | if (ret == NULL) { 133 | return NULL; 134 | } 135 | 136 | memset(ret, 0, count * size); 137 | return ret; 138 | } 139 | 140 | void *realloc(void *pointer, size_t size) { 141 | if (pointer == NULL) { 142 | return malloc(size); 143 | } 144 | 145 | struct malloc_metadata *metadata = (void *)((char *)pointer - sizeof(struct malloc_metadata)); 146 | if (DIV_ROUNDUP(metadata->size, BLOCK_SIZE) == DIV_ROUNDUP(size, BLOCK_SIZE)) { 147 | metadata->size = size; 148 | return pointer; 149 | } 150 | 151 | void *new_pointer = malloc(size); 152 | if (new_pointer == NULL) { 153 | return NULL; 154 | } 155 | 156 | if (metadata->size > size) { 157 | memcpy(new_pointer, pointer, size); 158 | } else { 159 | memcpy(new_pointer, pointer, metadata->size); 160 | } 161 | 162 | free(pointer); 163 | return new_pointer; 164 | } 165 | 166 | void free(void *pointer) { 167 | if (pointer == NULL) { 168 | return; 169 | } 170 | 171 | struct malloc_metadata *metadata = (void *)((char *)pointer - sizeof(struct malloc_metadata)); 172 | block_free(metadata, metadata->blocks); 173 | } 174 | -------------------------------------------------------------------------------- /source/libc/stdlib/misc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int atoi(const char *str) { 8 | return (int)strtol(str, (char **)NULL, 10); 9 | } 10 | 11 | long strtol(const char *str, char **endptr, int base) { 12 | long acc; 13 | long cutoff; 14 | int c; 15 | int neg; 16 | int any; 17 | int cutlim; 18 | 19 | /* 20 | * Skip white space and pick up leading +/- sign if any. 21 | * If base is 0, allow 0x for hex and 0 for octal, else 22 | * assume decimal; if base is already 16, allow 0x. 23 | */ 24 | const char *s = str; 25 | do { 26 | c = (unsigned char) *s++; 27 | } while (isspace(c)); 28 | if (c == '-') { 29 | neg = 1; 30 | c = *s++; 31 | } else { 32 | neg = 0; 33 | if (c == '+') 34 | c = *s++; 35 | } 36 | if ((base == 0 || base == 16) && 37 | c == '0' && (*s == 'x' || *s == 'X')) { 38 | c = s[1]; 39 | s += 2; 40 | base = 16; 41 | } 42 | if (base == 0) 43 | base = c == '0' ? 8 : 10; 44 | /* 45 | * Compute the cutoff value between legal numbers and illegal 46 | * numbers. That is the largest legal value, divided by the 47 | * base. An input number that is greater than this value, if 48 | * followed by a legal input character, is too big. One that 49 | * is equal to this value may be valid or not; the limit 50 | * between valid and invalid numbers is then based on the last 51 | * digit. For instance, if the range for longs is 52 | * [-2147483648..2147483647] and the input base is 10, 53 | * cutoff will be set to 214748364 and cutlim to either 54 | * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 55 | * a value > 214748364, or equal but the next digit is > 7 (or 8), 56 | * the number is too big, and we will return a range error. 57 | * 58 | * Set any if any `digits' consumed; make it negative to indicate 59 | * overflow. 60 | */ 61 | cutoff = neg ? LONG_MIN : LONG_MAX; 62 | cutlim = cutoff % base; 63 | cutoff /= base; 64 | if (neg) { 65 | if (cutlim > 0) { 66 | cutlim -= base; 67 | cutoff += 1; 68 | } 69 | cutlim = -cutlim; 70 | } 71 | for (acc = 0, any = 0;; c = (unsigned char) *s++) { 72 | if (isdigit(c)) 73 | c -= '0'; 74 | else if (isalpha(c)) 75 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 76 | else 77 | break; 78 | if (c >= base) 79 | break; 80 | if (any < 0) 81 | continue; 82 | if (neg) { 83 | if (acc < cutoff || (acc == cutoff && c > cutlim)) { 84 | any = -1; 85 | acc = LONG_MIN; 86 | errno = ERANGE; 87 | } else { 88 | any = 1; 89 | acc *= base; 90 | acc -= c; 91 | } 92 | } else { 93 | if (acc > cutoff || (acc == cutoff && c > cutlim)) { 94 | any = -1; 95 | acc = LONG_MAX; 96 | errno = ERANGE; 97 | } else { 98 | any = 1; 99 | acc *= base; 100 | acc += c; 101 | } 102 | } 103 | } 104 | if (endptr != 0) 105 | *endptr = (char *) (any ? s - 1 : str); 106 | return (acc); 107 | } 108 | -------------------------------------------------------------------------------- /source/libc/stdlib/sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void swap(void *x, void *y, size_t l) { 6 | char *a = x; 7 | char *b = y; 8 | while(l--) { 9 | char c = *a; 10 | *a++ = *b; 11 | *b++ = c; 12 | } 13 | } 14 | 15 | static void inner_sort(char *array, size_t size, int (*cmp)(const void*, const void*), int begin, int end) { 16 | if (end > begin) { 17 | void *pivot = array + begin; 18 | int l = begin + size; 19 | int r = end; 20 | while(l < r) { 21 | if (cmp(array + l, pivot) <= 0) { 22 | l += size; 23 | } else if (cmp(array + r, pivot) > 0) { 24 | r -= size; 25 | } else if ( l < r ) { 26 | swap(array + l, array + r, size); 27 | } 28 | } 29 | l -= size; 30 | swap(array+begin, array+l, size); 31 | inner_sort(array, size, cmp, begin, l); 32 | inner_sort(array, size, cmp, r, end); 33 | } 34 | } 35 | 36 | void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *)) { 37 | if (count > 0) { 38 | inner_sort(base, size, compare, 0, (count - 1) * size); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/libc/string/cstring.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | size_t strlen(const char *str) { 6 | int i; 7 | for (i = 0; str[i]; i++); 8 | return i; 9 | } 10 | 11 | int strcmp(const char *str1, const char *str2) { 12 | for (size_t i = 0; ; i++) { 13 | char c1 = str1[i]; 14 | char c2 = str2[i]; 15 | if (c1 != c2) { 16 | return c1 < c2 ? -1 : 1; 17 | } 18 | if (!c1) { 19 | return 0; 20 | } 21 | } 22 | } 23 | 24 | int strncmp(const char *str1, const char *str2, size_t num) { 25 | for (size_t i = 0; i < num; i++) { 26 | char c1 = str1[i]; 27 | char c2 = str2[i]; 28 | if (c1 != c2) { 29 | return c1 < c2 ? -1 : 1; 30 | } 31 | if (!c1) { 32 | return 0; 33 | } 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | char *strcpy(char *destination, const char *source) { 40 | size_t i; 41 | for (i = 0; source[i]; i++) { 42 | destination[i] = source[i]; 43 | } 44 | destination[i] = '\0'; 45 | return destination; 46 | } 47 | 48 | char *strncpy(char *destination, const char *source, size_t count) { 49 | size_t i; 50 | 51 | for (i = 0; i < count && source[i]; i++) { 52 | destination[i] = source[i]; 53 | } 54 | 55 | for (; i < count; i++) { 56 | destination[i] = 0; 57 | } 58 | 59 | return destination; 60 | } 61 | 62 | char *strcat(char *destination, const char *source) { 63 | char *ret = destination; 64 | 65 | while (*destination != '\0') { 66 | destination++; 67 | } 68 | 69 | while ((*destination++ = *source++)); 70 | 71 | return ret; 72 | } 73 | 74 | char *strchr(const char *string, int c) { 75 | for (size_t i = 0; ; i++) { 76 | if (string[i] == c) { 77 | return (char *)&string[i]; 78 | } 79 | if (string[i] == 0) { 80 | return NULL; 81 | } 82 | } 83 | } 84 | 85 | char *strrchr(const char *string, int c) { 86 | for (size_t i = 0, last_index = 0; ; i++) { 87 | if (string[i] == c) { 88 | last_index = i; 89 | } 90 | if (string[i] == 0) { 91 | return (char *)&string[last_index]; 92 | } 93 | } 94 | } 95 | 96 | char *strstr(const char *string, const char *searched) { 97 | size_t searched_len = strlen(searched); 98 | 99 | for (size_t i = 0; string[i]; i++) { 100 | if (string[i] != searched[i]) { 101 | continue; 102 | } 103 | if (strncmp(&string[i], searched, searched_len) == 0) { 104 | return (char *)&string[i]; 105 | } 106 | } 107 | 108 | return NULL; 109 | } 110 | 111 | char *strpbrk(const char *string, const char *searched) { 112 | while (*string) { 113 | if (strchr(searched, *string++)) { 114 | return (char*)--string; 115 | } 116 | } 117 | 118 | return NULL; 119 | } 120 | 121 | char *strsignal(int signal) { 122 | return (char *)sys_siglist[signal]; 123 | } 124 | -------------------------------------------------------------------------------- /source/libc/string/mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void *memset(void *destination, int value, size_t count) { 6 | uint8_t *ptr = destination; 7 | 8 | for (size_t i = 0; i < count; i++) { 9 | ptr[i] = (uint8_t)value; 10 | } 11 | 12 | return destination; 13 | } 14 | 15 | void *memcpy(void *destination, const void *source, size_t count) { 16 | uint8_t *dest = destination; 17 | const uint8_t *src = source; 18 | 19 | for (size_t i = 0; i < count; i++) { 20 | dest[i] = src[i]; 21 | } 22 | 23 | return dest; 24 | } 25 | 26 | int memcmp(const void *source1, const void *source2, size_t count) { 27 | const uint8_t *src1 = source1; 28 | const uint8_t *src2 = source2; 29 | 30 | for (size_t i = 0; i < count; i++) { 31 | if (src1[i] != src2[i]) { 32 | return src1[i] < src2[i] ? -1 : 1; 33 | } 34 | } 35 | 36 | return 0; 37 | } 38 | 39 | void *memmove(void *destination, const void *source, size_t count) { 40 | uint8_t *dest = destination; 41 | const uint8_t *src = source; 42 | 43 | if (source > destination) { 44 | for (size_t i = 0; i < count; i++) { 45 | dest[i] = src[i]; 46 | } 47 | } else if (source < destination) { 48 | for (size_t i = count; i > 0; i--) { 49 | dest[i - 1] = src[i - 1]; 50 | } 51 | } 52 | 53 | return dest; 54 | } 55 | -------------------------------------------------------------------------------- /source/libc/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | time_t time(time_t *store) { 4 | struct timespec t; 5 | if (clock_gettime(CLOCK_REALTIME, &t)) { 6 | return (time_t)-1; 7 | } 8 | 9 | if (store != NULL) { 10 | *store = t.tv_sec; 11 | } 12 | return t.tv_sec; 13 | } 14 | -------------------------------------------------------------------------------- /source/libc/unistd/brk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char **environ; 5 | 6 | int brk(void *address) { 7 | intptr_t current_brk = (intptr_t)sbrk(0); 8 | intptr_t brk_diff = (intptr_t)address - current_brk; 9 | if (sbrk(brk_diff) == (void*)-1) { 10 | return -1; 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /source/libc/unistd/dup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int dup(int fd) { 5 | return fcntl(fd, F_DUPFD, 0); 6 | } 7 | 8 | int dup2(int fd, int fd2) { 9 | close(fd2); 10 | return fcntl(fd, F_DUPFD, fd2); 11 | } 12 | -------------------------------------------------------------------------------- /source/libc/unistd/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // TODO: Using a fixed amount of parameters could become a bug in the near 8 | // future. 9 | 10 | static void get_args(char *argv[], char **envp[], const char *arg0, va_list args) { 11 | size_t i = 0; 12 | argv[i++] = (char *)arg0; 13 | 14 | if (arg0 != NULL) { 15 | for (;;) { 16 | char *arg = va_arg(args, char *); 17 | if (arg == NULL) { 18 | break; 19 | } 20 | argv[i++] = arg; 21 | } 22 | } 23 | 24 | argv[i++] = NULL; 25 | if (envp != NULL) { 26 | *envp = va_arg(args, char **); 27 | } 28 | } 29 | 30 | int execl(const char *path, const char *arg0, ...) { 31 | va_list args; 32 | va_start(args, arg0); 33 | 34 | char *argv[40]; 35 | get_args(argv, NULL, arg0, args); 36 | 37 | va_end(args); 38 | return execve(path, argv, environ); 39 | } 40 | 41 | int execv(const char *path, char *const argv[]) { 42 | return execve(path, argv, environ); 43 | } 44 | 45 | int execle(const char *path, const char *arg0, ...) { 46 | va_list args; 47 | va_start(args, arg0); 48 | 49 | char *argv[40]; 50 | char **envp; 51 | get_args(argv, &envp, arg0, args); 52 | 53 | va_end(args); 54 | return execve(path, argv, envp); 55 | } 56 | 57 | int execlp(const char *file, const char *arg0, ...) { 58 | va_list args; 59 | va_start(args, arg0); 60 | 61 | char *argv[40]; 62 | get_args(argv, NULL, arg0, args); 63 | 64 | va_end(args); 65 | return execvpe(file, argv, environ); 66 | } 67 | 68 | int execvp(const char *file, char *const argv[]) { 69 | return execvpe(file, argv, environ); 70 | } 71 | 72 | int execvpe(const char *file, char *const argv[], char *const envp[]) { 73 | if (strchr(file, '/')) { 74 | return execve(file, argv, envp); 75 | } 76 | 77 | char *search_path = getenv("PATH"); 78 | if (search_path == NULL) { 79 | search_path = "/bin:/usr/bin"; 80 | } 81 | 82 | for (;;) { 83 | char path[100] = {0}; 84 | char *curr_search = strchr(search_path, '/'); 85 | char *curr_end = strchr(search_path, ':'); 86 | size_t curr_len = curr_end - curr_search; 87 | strncpy(path, curr_search, curr_len); 88 | strcpy(path + curr_len, "/"); 89 | strcpy(path + curr_len + 1, file); 90 | execve(path, argv, envp); 91 | if (errno == ENOEXEC) { 92 | char *const shell_argv[] = {path, NULL}; 93 | return execve(shell_argv[0], shell_argv, envp); 94 | } else if (curr_end == NULL) { 95 | break; 96 | } else { 97 | search_path = curr_end + 1; 98 | } 99 | } 100 | 101 | return -1; 102 | } 103 | -------------------------------------------------------------------------------- /source/libc/unistd/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned sleep(unsigned seconds) { 5 | struct timespec tv = { .tv_sec = seconds, .tv_nsec = 0 }; 6 | if (nanosleep(&tv, &tv)) { 7 | return tv.tv_sec; 8 | } 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /source/libc/unistd/tty.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static char name[TTY_NAME_MAX]; 5 | 6 | char *ttyname(int fd) { 7 | if (ttyname_r(fd, name, TTY_NAME_MAX) != 0) { 8 | return NULL; 9 | } 10 | 11 | return name; 12 | } 13 | 14 | int isatty(int fd) { 15 | struct termios t; 16 | return tcgetattr(fd, &t) == 0; 17 | } 18 | -------------------------------------------------------------------------------- /source/libm/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int isnan(double x) { 5 | return x == 0x7F800001; 6 | } 7 | 8 | double fmod(double x, double y) { 9 | // Shamelessly copied from musl. 10 | union {double f; uint64_t i;} ux = {x}, uy = {y}; 11 | int ex = ux.i>>52 & 0x7ff; 12 | int ey = uy.i>>52 & 0x7ff; 13 | int sx = ux.i>>63; 14 | uint64_t i; 15 | 16 | /* in the followings uxi should be ux.i, but then gcc wrongly adds */ 17 | /* float load/store to inner loops ruining performance and code size */ 18 | uint64_t uxi = ux.i; 19 | 20 | if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) 21 | return (x*y)/(x*y); 22 | if (uxi<<1 <= uy.i<<1) { 23 | if (uxi<<1 == uy.i<<1) 24 | return 0*x; 25 | return x; 26 | } 27 | 28 | /* normalize x and y */ 29 | if (!ex) { 30 | for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); 31 | uxi <<= -ex + 1; 32 | } else { 33 | uxi &= -1ULL >> 12; 34 | uxi |= 1ULL << 52; 35 | } 36 | if (!ey) { 37 | for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); 38 | uy.i <<= -ey + 1; 39 | } else { 40 | uy.i &= -1ULL >> 12; 41 | uy.i |= 1ULL << 52; 42 | } 43 | 44 | /* x mod y */ 45 | for (; ex > ey; ex--) { 46 | i = uxi - uy.i; 47 | if (i >> 63 == 0) { 48 | if (i == 0) 49 | return 0*x; 50 | uxi = i; 51 | } 52 | uxi <<= 1; 53 | } 54 | i = uxi - uy.i; 55 | if (i >> 63 == 0) { 56 | if (i == 0) 57 | return 0*x; 58 | uxi = i; 59 | } 60 | for (; uxi>>52 == 0; uxi <<= 1, ex--); 61 | 62 | /* scale result */ 63 | if (ex > 0) { 64 | uxi -= 1ULL << 52; 65 | uxi |= (uint64_t)ex << 52; 66 | } else { 67 | uxi >>= -ex + 1; 68 | } 69 | uxi |= (uint64_t)sx << 63; 70 | ux.i = uxi; 71 | return ux.f; 72 | } 73 | 74 | // Take an arbitrary angle and normalize it to [-PI/PI]. 75 | #define NORMALIZE_ANGLE(x) fmod(x, 2.0 * M_PI) 76 | 77 | double sin(double rad) { 78 | // We can re-express sin(x) as a weighted sum of powers of x: 79 | // sin(x) = a + a1x + a2x2 + ... + anxn 80 | // We can re-express this as 81 | // sin(x) = a + a1 * T0(x) + a2 * T1(x) + ... + an * Tn(x) 82 | // where Tn(x) is a first kind chebyshev polynomial. 83 | // We can approximate with a finite number of polynomial, with 84 | // 7 terms we can yield a great precission. (calculating it would be great) 85 | // We will use the odd exponents given the symetry of chebyshev (says the internet). 86 | // At last, will use Horner's method (said the maths teacher to do in this cases idk). 87 | // TODO: Explaining a bit better would be optimal. 88 | double coefficients[] = { 89 | 0.999999999973088, // x 90 | -0.1666666663960699, // x^3 91 | 0.00833333287058762, // x^5 92 | -0.0001984123883227529, // x^7, 93 | 2.755627491096882e-6, // x^9 94 | -2.503262029557047e-8, // x^11 95 | 1.58535563425041e-10, // x^13 96 | }; 97 | 98 | // Normalize. 99 | double x = NORMALIZE_ANGLE(rad); 100 | 101 | double x2 = x * x; 102 | 103 | double p13 = coefficients[6]; 104 | double p11 = p13 * x2 + coefficients[5]; 105 | double p9 = p11 * x2 + coefficients[4]; 106 | double p7 = p9 * x2 + coefficients[3]; 107 | double p5 = p7 * x2 + coefficients[2]; 108 | double p3 = p5 * x2 + coefficients[1]; 109 | double p1 = p3 * x2 + coefficients[0]; 110 | 111 | return p1 * x; 112 | } 113 | 114 | double cos(double rad) { 115 | // Sweet elementary math. 116 | return sin(M_PI / 2 - rad); 117 | } 118 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/crt0.S: -------------------------------------------------------------------------------- 1 | .section .text 2 | .globl _start 3 | _start: 4 | xor %ebp, %ebp // Mark the end of stack frames 5 | push $0 // envp which we dont have :) 6 | push $0x1010 // Argv from hardcoded memory 7 | push (0x1000) // Argc from hardcoded memory 8 | xor %eax, %eax // Per ABI and compatibility with icc 9 | call __slibc_init // Hand it off to the libc. 10 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/siglist.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int sys_nsig = 32; 4 | 5 | const char *const sys_siglist[] = { 6 | [SIGHUP] = "Hangup", 7 | [SIGINT] = "Terminal interrupt signal", 8 | [SIGQUIT] = "Terminal quit signal", 9 | [SIGILL] = "Illegal instruction", 10 | [SIGTRAP] = "Trace/breakpoint trap", 11 | [SIGABRT] = "Process abort signal", 12 | [SIGBUS] = "Access to an undefined portion of a memory object", 13 | [SIGFPE] = "Erroneous arithmetic operation", 14 | [SIGKILL] = "Kill (cannot be caught or ignored)", 15 | [SIGUSR1] = "User-defined signal 1", 16 | [SIGSEGV] = "Invalid memory reference", 17 | [SIGUSR2] = "User-defined signal 2", 18 | [SIGPIPE] = "Write on a pipe with no one to read it", 19 | [SIGTERM] = "Termination signal", 20 | [SIGSTKFLT] = "Stack fault", 21 | [SIGCHLD] = "Child process terminated, stopped", 22 | [SIGCONT] = "Continue executing, if stopped", 23 | [SIGSTOP] = "Stop executing (cannot be caught or ignored)", 24 | [SIGTSTP] = "Terminal stop signal", 25 | [SIGTTIN] = "Background process attempting read", 26 | [SIGTTOU] = "Background process attempting write", 27 | [SIGURG] = "High bandwidth data is available at a socket", 28 | [SIGXCPU] = "CPU time limit exceeded", 29 | [SIGXFSZ] = "File size limit exceeded", 30 | [SIGVTALRM] = "Virtual timer expired", 31 | [SIGPROF] = "Profiling timer expired", 32 | [SIGWINCH] = "Window size change", 33 | [SIGPOLL] = "Pollable event", 34 | [SIGPWR] = "Power failure restart", 35 | [SIGSYS] = "Bad system call", 36 | [SIGRTMIN] = "Real time signal min range", 37 | [SIGRTMAX] = "Real time signal max range" 38 | }; 39 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint16_t OS_new_segment(int arg1, int arg2, int arg3) { 5 | uint16_t return_val; 6 | uint32_t discard; 7 | asm volatile ( "movl $0x06, %%eax\n\t" 8 | "int $0x80\n\t" 9 | : "=a" (return_val), "=d"(discard) 10 | : "c" (arg1), 11 | "d" (arg2), 12 | "D" (arg3) 13 | : ); 14 | return return_val; 15 | } 16 | 17 | uint32_t OS_get_heap_base(void) { 18 | uint32_t val; 19 | asm volatile ( "movl $0x10, %%eax\n\t" 20 | "int $0x80\n\t" 21 | : "=a" (val) 22 | : 23 | : "edx" ); 24 | return val; 25 | } 26 | 27 | uint32_t OS_get_heap_size(void) { 28 | uint32_t val; 29 | asm volatile ( "movl $0x11, %%eax\n\t" 30 | "int $0x80\n\t" 31 | : "=a" (val) 32 | : 33 | : "edx" ); 34 | return val; 35 | } 36 | int OS_resize_heap(size_t size) { 37 | int return_val; 38 | asm volatile ( "movl $0x12, %%eax\n\t" 39 | "int $0x80\n\t" 40 | : "=a" (return_val) 41 | : "c" (size) 42 | : "edx" ); 43 | return return_val; 44 | } 45 | 46 | int OS_vdev_register(uint8_t *in, uint8_t *out, int *flag_in, int *flag_out) { 47 | int ret; 48 | asm volatile ( "movl $0x20, %%eax\n\t" 49 | "int $0x80\n\t" 50 | : "=a" (ret) 51 | : "c" (in), 52 | "d" (flag_in), 53 | "D" (out), 54 | "S" (flag_out) 55 | : ); 56 | return ret; 57 | } 58 | 59 | int OS_vdev_in_ready(void *value) { 60 | int ret; 61 | asm volatile ( "movl $0x21, %%eax\n\t" 62 | "int $0x80\n\t" 63 | : "=a" (ret) 64 | : "c" (value) 65 | : "edx" ); 66 | return ret; 67 | } 68 | 69 | int OS_vdev_out_ready(void *value) { 70 | int ret; 71 | asm volatile ( "movl $0x22, %%eax\n\t" 72 | "int $0x80\n\t" 73 | : "=a" (ret) 74 | : "c" (value) 75 | : "edx" ); 76 | return ret; 77 | } 78 | 79 | int OS_vdev_await(void) { 80 | int ret; 81 | asm volatile ( "movl $0x23, %%eax\n\t" 82 | "int $0x80\n\t" 83 | : "=a" (ret) 84 | : 85 | : "edx" ); 86 | return ret; 87 | } 88 | 89 | int OS_read(int fd, void *buffer, size_t len) { 90 | int return_val, discard; 91 | asm volatile ( "int $0x80\n\t" 92 | : "=a" (return_val), "=d"(discard) 93 | : "a"(0x2c), "c" (fd), 94 | "d" (buffer), 95 | "D" (len) 96 | : "memory"); 97 | return return_val; 98 | } 99 | 100 | int OS_close(int fd) { 101 | int return_val; 102 | asm volatile ( "movl $0x2b, %%eax\n\t" 103 | "int $0x80\n\t" 104 | : "=a" (return_val) 105 | : "c" (fd) 106 | : "edx" ); 107 | return return_val; 108 | } 109 | 110 | int OS_open(const char *path, int flags, mode_t mode) { 111 | int return_val; 112 | asm volatile ( "movl $0x2a, %%eax\n\t" 113 | "int $0x80\n\t" 114 | : "=a" (return_val) 115 | : "c" (path), 116 | "d" (flags), 117 | "D" (mode) 118 | : ); 119 | return return_val; 120 | } 121 | 122 | int OS_write(int fd, const void *buffer, size_t len) { 123 | int return_val, discard; 124 | asm volatile ( "int $0x80\n\t" 125 | : "=a" (return_val), "=d"(discard) 126 | : "a"(0x2d), "c" (fd), 127 | "d" (buffer), 128 | "D" (len) 129 | : "memory"); 130 | return return_val; 131 | } 132 | 133 | int OS_vfs_mkdir(const char *path, int perms) { 134 | int ret; 135 | asm volatile ( "movl $0x35, %%eax\n\t" 136 | "int $0x80\n\t" 137 | : "=a" (ret) 138 | : "c" (path), 139 | "d" (perms) 140 | : ); 141 | return ret; 142 | } 143 | 144 | int OS_vfs_create(const char *path, int perms) { 145 | int ret; 146 | asm volatile ( "movl $0x36, %%eax\n\t" 147 | "int $0x80\n\t" 148 | : "=a" (ret) 149 | : "c" (path), 150 | "d" (perms) 151 | : ); 152 | return ret; 153 | } 154 | 155 | int OS_vfs_remove(const char *path) { 156 | int return_val; 157 | asm volatile ( "movl $0x34, %%eax\n\t" 158 | "int $0x80\n\t" 159 | : "=a" (return_val) 160 | : "c" (path) 161 | : "edx" ); 162 | return return_val; 163 | } 164 | 165 | int OS_vfs_list(const char *path, vfs_metadata_t *metadata, size_t entry) { 166 | int return_val; 167 | asm volatile ( "movl $0x32, %%eax\n\t" 168 | "int $0x80\n\t" 169 | : "=a" (return_val) 170 | : "c" (path), 171 | "d" (metadata), 172 | "D" (entry) 173 | : ); 174 | return return_val; 175 | } 176 | 177 | int OS_vfs_write(const char *path, size_t loc, const void *value) { 178 | int return_val; 179 | uint32_t loc_low = loc & 0x00000000ffffffff; 180 | uint32_t loc_high = loc / 0x100000000; 181 | asm volatile ( "movl $0x31, %%eax\n\t" 182 | "int $0x80\n\t" 183 | : "=a" (return_val) 184 | : "c" (path), 185 | "d" (loc_low), 186 | "D" (loc_high), 187 | "S" (value) 188 | : ); 189 | return return_val; 190 | } 191 | 192 | int OS_vfs_read(const char *path, size_t loc) { 193 | int return_val; 194 | uint32_t loc_low = loc & 0x00000000ffffffff; 195 | uint32_t loc_high = loc / 0x100000000; 196 | asm volatile ( "movl $0x30, %%eax\n\t" 197 | "int $0x80\n\t" 198 | : "=a" (return_val) 199 | : "c" (path), 200 | "d" (loc_low), 201 | "D" (loc_high) 202 | : ); 203 | return return_val; 204 | } 205 | 206 | int OS_vfs_cd(const char *path) { 207 | int return_val; 208 | asm volatile ( "movl $0x2f, %%eax\n\t" 209 | "int $0x80\n\t" 210 | : "=a" (return_val) 211 | : "c" (path) 212 | : "edx" ); 213 | return return_val; 214 | } 215 | 216 | int OS_vfs_get_metadata(const char *path, vfs_metadata_t *metadata, int type) { 217 | int return_val; 218 | asm volatile ( "movl $0x33, %%eax\n\t" 219 | "int $0x80\n\t" 220 | : "=a" (return_val) 221 | : "c" (path), 222 | "d" (metadata), 223 | "D" (type) 224 | : ); 225 | return return_val; 226 | } 227 | 228 | void OS_pwd(const char *value) { 229 | asm volatile ( "movl $0x1a, %%eax\n\t" 230 | "int $0x80\n\t" 231 | : 232 | : "c" (value) 233 | : "eax", "edx" ); 234 | } 235 | 236 | int OS_general_execute_block(task_info_t *taskinfo) { 237 | uint32_t ret_low; 238 | uint32_t ret_hi; 239 | uint64_t ret; 240 | asm volatile ( "movl $0x02, %%eax\n\t" 241 | "int $0x80\n\t" 242 | : "=a" (ret_low), 243 | "=d" (ret_hi) 244 | : "c" (taskinfo) 245 | : ); 246 | ret = ((uint64_t)(ret_hi) << 32) + (uint64_t)ret_low; 247 | return ret; 248 | } 249 | 250 | int OS_general_execute(task_info_t *taskinfo) { 251 | int ret; 252 | asm volatile ( "movl $0x01, %%eax\n\t" 253 | "int $0x80\n\t" 254 | : "=a" (ret) 255 | : "c" (taskinfo) 256 | : "edx" ); 257 | return ret; 258 | } 259 | 260 | void OS_what_stdin(const char *path) { 261 | asm volatile ( "movl $0x1b, %%eax\n\t" 262 | "int $0x80\n\t" 263 | : 264 | : "c" (path) 265 | : "eax", "edx" ); 266 | } 267 | 268 | void OS_what_stdout(const char *path) { 269 | asm volatile ( "movl $0x1c, %%eax\n\t" 270 | "int $0x80\n\t" 271 | : 272 | : "c" (path) 273 | : "eax", "edx" ); 274 | } 275 | 276 | void OS_what_stderr(const char *path) { 277 | asm volatile ( "movl $0x1d, %%eax\n\t" 278 | "int $0x80\n\t" 279 | : 280 | : "c" (path) 281 | : "eax", "edx" ); 282 | } 283 | 284 | pid_t OS_ipc_resolve_name(const char *server) { 285 | pid_t pid; 286 | asm volatile ( "movl $0x0a, %%eax\n\t" 287 | "int $0x80\n\t" 288 | : "=a" (pid) 289 | : "c" (server) 290 | : "edx" ); 291 | return pid; 292 | } 293 | 294 | void OS_ipc_send_packet(pid_t pid, void *payload, size_t len) { 295 | asm volatile ( "movl $0x08, %%eax\n\t" 296 | "int $0x80\n\t" 297 | : 298 | : "c" (pid), 299 | "d" (payload), 300 | "D" (len) 301 | : "eax" ); 302 | } 303 | 304 | pid_t OS_getpid(void) { 305 | pid_t val; 306 | asm volatile ( "movl $0x15, %%eax\n\t" 307 | "int $0x80\n\t" 308 | : "=a" (val) 309 | : 310 | : "edx" ); 311 | return val; 312 | } 313 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/api.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__API_H__ 2 | #define __SYS__API_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define VFS_FILE_TYPE 0 13 | #define VFS_DIRECTORY_TYPE 1 14 | #define VFS_DEVICE_TYPE 2 15 | #define VFS_SUCCESS 0 16 | #define VFS_FAILURE -2 17 | 18 | typedef struct { 19 | char filename[2048]; 20 | int filetype; 21 | uint64_t size; 22 | } vfs_metadata_t; 23 | 24 | typedef struct { 25 | char* path; 26 | char* ti_stdin; 27 | char* ti_stdout; 28 | char* ti_stderr; 29 | char* pwd; 30 | char* name; 31 | char* server_name; 32 | int argc; 33 | char** argv; 34 | } task_info_t; 35 | 36 | uint16_t OS_new_segment(int arg1, int arg2, int arg3); 37 | uint32_t OS_get_heap_base(void); 38 | uint32_t OS_get_heap_size(void); 39 | int OS_resize_heap(size_t size); 40 | int OS_vdev_register(uint8_t *in, uint8_t *out, int *flag_in, int *flag_out); 41 | int OS_vdev_in_ready(void *value); 42 | int OS_vdev_out_ready(void *value); 43 | int OS_vdev_await(void); 44 | int OS_read(int fd, void *buffer, size_t len); 45 | int OS_close(int fd); 46 | int OS_open(const char *path, int flags, mode_t mode); 47 | int OS_write(int fd, const void *buffer, size_t len); 48 | int OS_vfs_mkdir(const char *path, int perms); 49 | int OS_vfs_create(const char *path, int perms); 50 | int OS_vfs_remove(const char *path); 51 | int OS_vfs_list(const char *path, vfs_metadata_t *metadata, size_t entry); 52 | int OS_vfs_write(const char *path, size_t loc, const void *value); 53 | int OS_vfs_read(const char *path, size_t loc); 54 | int OS_vfs_cd(const char *path); 55 | int OS_vfs_get_metadata(const char *path, vfs_metadata_t *metadata, int type); 56 | void OS_pwd(const char *value); 57 | int OS_general_execute_block(task_info_t *taskinfo); 58 | int OS_general_execute(task_info_t *taskinfo); 59 | void OS_what_stdin(const char *path); 60 | void OS_what_stdout(const char *path); 61 | void OS_what_stderr(const char *path); 62 | pid_t OS_ipc_resolve_name(const char *server); 63 | void OS_ipc_send_packet(pid_t pid, void *payload, size_t len); 64 | pid_t OS_getpid(void); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/errnoval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__ERRNOVAL_H__ 2 | #define __SYS__ERRNOVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // Echidna doesnt use errno apparently so I just copied the linux ones. 9 | // Ought to do. 10 | 11 | // All of them shamelessly copied from 12 | // https://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html 13 | // Give them a hug on my behalf. 14 | 15 | #define EPERM 1 /* Operation not permitted */ 16 | #define ENOENT 2 /* No such file or directory */ 17 | #define ESRCH 3 /* No such process */ 18 | #define EINTR 4 /* Interrupted system call */ 19 | #define EIO 5 /* I/O error */ 20 | #define ENXIO 6 /* No such device or address */ 21 | #define E2BIG 7 /* Arg list too long */ 22 | #define ENOEXEC 8 /* Exec format error */ 23 | #define EBADF 9 /* Bad file number */ 24 | #define ECHILD 10 /* No child processes */ 25 | #define EAGAIN 11 /* Try again */ 26 | #define ENOMEM 12 /* Out of memory */ 27 | #define EACCES 13 /* Permission denied */ 28 | #define EFAULT 14 /* Bad address */ 29 | #define ENOTBLK 15 /* Block device required */ 30 | #define EBUSY 16 /* Device or resource busy */ 31 | #define EEXIST 17 /* File exists */ 32 | #define EXDEV 18 /* Cross-device link */ 33 | #define ENODEV 19 /* No such device */ 34 | #define ENOTDIR 20 /* Not a directory */ 35 | #define EISDIR 21 /* Is a directory */ 36 | #define EINVAL 22 /* Invalid argument */ 37 | #define ENFILE 23 /* File table overflow */ 38 | #define EMFILE 24 /* Too many open files */ 39 | #define ENOTTY 25 /* Not a typewriter */ 40 | #define ETXTBSY 26 /* Text file busy */ 41 | #define EFBIG 27 /* File too large */ 42 | #define ENOSPC 28 /* No space left on device */ 43 | #define ESPIPE 29 /* Illegal seek */ 44 | #define EROFS 30 /* Read-only file system */ 45 | #define EMLINK 31 /* Too many links */ 46 | #define EPIPE 32 /* Broken pipe */ 47 | #define EDOM 33 /* Math argument out of domain of func */ 48 | #define ERANGE 34 /* Math result not representable */ 49 | #define EDEADLK 35 /* Resource deadlock would occur */ 50 | #define ENAMETOOLONG 36 /* File name too long */ 51 | #define ENOLCK 37 /* No record locks available */ 52 | #define ENOSYS 38 /* Function not implemented */ 53 | #define ENOTEMPTY 39 /* Directory not empty */ 54 | #define ELOOP 40 /* Too many symbolic links encountered */ 55 | #define EWOULDBLOCK EAGAIN /* Operation would block */ 56 | #define ENOMSG 42 /* No message of desired type */ 57 | #define EIDRM 43 /* Identifier removed */ 58 | #define ECHRNG 44 /* Channel number out of range */ 59 | #define EL2NSYNC 45 /* Level 2 not synchronized */ 60 | #define EL3HLT 46 /* Level 3 halted */ 61 | #define EL3RST 47 /* Level 3 reset */ 62 | #define ELNRNG 48 /* Link number out of range */ 63 | #define EUNATCH 49 /* Protocol driver not attached */ 64 | #define ENOCSI 50 /* No CSI structure available */ 65 | #define EL2HLT 51 /* Level 2 halted */ 66 | #define EBADE 52 /* Invalid exchange */ 67 | #define EBADR 53 /* Invalid request descriptor */ 68 | #define EXFULL 54 /* Exchange full */ 69 | #define ENOANO 55 /* No anode */ 70 | #define EBADRQC 56 /* Invalid request code */ 71 | #define EBADSLT 57 /* Invalid slot */ 72 | #define EDEADLOCK EDEADLK 73 | #define EBFONT 59 /* Bad font file format */ 74 | #define ENOSTR 60 /* Device not a stream */ 75 | #define ENODATA 61 /* No data available */ 76 | #define ETIME 62 /* Timer expired */ 77 | #define ENOSR 63 /* Out of streams resources */ 78 | #define ENONET 64 /* Machine is not on the network */ 79 | #define ENOPKG 65 /* Package not installed */ 80 | #define EREMOTE 66 /* Object is remote */ 81 | #define ENOLINK 67 /* Link has been severed */ 82 | #define EADV 68 /* Advertise error */ 83 | #define ESRMNT 69 /* Srmount error */ 84 | #define ECOMM 70 /* Communication error on send */ 85 | #define EPROTO 71 /* Protocol error */ 86 | #define EMULTIHOP 72 /* Multihop attempted */ 87 | #define EDOTDOT 73 /* RFS specific error */ 88 | #define EBADMSG 74 /* Not a data message */ 89 | #define EOVERFLOW 75 /* Value too large for defined data type */ 90 | #define ENOTUNIQ 76 /* Name not unique on network */ 91 | #define EBADFD 77 /* File descriptor in bad state */ 92 | #define EREMCHG 78 /* Remote address changed */ 93 | #define ELIBACC 79 /* Can not access a needed shared library */ 94 | #define ELIBBAD 80 /* Accessing a corrupted shared library */ 95 | #define ELIBSCN 81 /* .lib section in a.out corrupted */ 96 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ 97 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */ 98 | #define EILSEQ 84 /* Illegal byte sequence */ 99 | #define ERESTART 85 /* Interrupted system call should be restarted */ 100 | #define ESTRPIPE 86 /* Streams pipe error */ 101 | #define EUSERS 87 /* Too many users */ 102 | #define ENOTSOCK 88 /* Socket operation on non-socket */ 103 | #define EDESTADDRREQ 89 /* Destination address required */ 104 | #define EMSGSIZE 90 /* Message too long */ 105 | #define EPROTOTYPE 91 /* Protocol wrong type for socket */ 106 | #define ENOPROTOOPT 92 /* Protocol not available */ 107 | #define EPROTONOSUPPORT 93 /* Protocol not supported */ 108 | #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ 109 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 110 | #define ENOTSUPP EOPNOTSUPP 111 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ 112 | #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ 113 | #define EADDRINUSE 98 /* Address already in use */ 114 | #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ 115 | #define ENETDOWN 100 /* Network is down */ 116 | #define ENETUNREACH 101 /* Network is unreachable */ 117 | #define ENETRESET 102 /* Network dropped connection because of reset */ 118 | #define ECONNABORTED 103 /* Software caused connection abort */ 119 | #define ECONNRESET 104 /* Connection reset by peer */ 120 | #define ENOBUFS 105 /* No buffer space available */ 121 | #define EISCONN 106 /* Transport endpoint is already connected */ 122 | #define ENOTCONN 107 /* Transport endpoint is not connected */ 123 | #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ 124 | #define ETOOMANYREFS 109 /* Too many references: cannot splice */ 125 | #define ETIMEDOUT 110 /* Connection timed out */ 126 | #define ECONNREFUSED 111 /* Connection refused */ 127 | #define EHOSTDOWN 112 /* Host is down */ 128 | #define EHOSTUNREACH 113 /* No route to host */ 129 | #define EALREADY 114 /* Operation already in progress */ 130 | #define EINPROGRESS 115 /* Operation now in progress */ 131 | #define ESTALE 116 /* Stale NFS file handle */ 132 | #define EUCLEAN 117 /* Structure needs cleaning */ 133 | #define ENOTNAM 118 /* Not a XENIX named type file */ 134 | #define ENAVAIL 119 /* No XENIX semaphores available */ 135 | #define EISNAM 120 /* Is a named type file */ 136 | #define EREMOTEIO 121 /* Remote I/O error */ 137 | #define EDQUOT 122 /* Quota exceeded */ 138 | #define ENOMEDIUM 123 /* No medium found */ 139 | #define EMEDIUMTYPE 124 /* Wrong medium type */ 140 | 141 | #ifdef __cplusplus 142 | } 143 | #endif 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/fcntlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__FCNTLVAL_H__ 2 | #define __SYS__FCNTLVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define O_RDONLY (1 << 0) 9 | #define O_WRONLY (1 << 1) 10 | #define O_RDWR (1 << 2) 11 | #define O_APPEND (1 << 3) 12 | #define O_CREAT (1 << 4) 13 | #define O_TRUNC (1 << 5) 14 | #define O_EXCL (1 << 6) 15 | 16 | #define SEEK_SET 0 17 | #define SEEK_END 1 18 | #define SEEK_CUR 2 19 | 20 | #define F_SETFD 69 // Placeholder cuz echidnaOS has no fcntl. 21 | #define F_DUPFD 69 // Placeholder cuz echidnaOS has no fcntl. 22 | 23 | #define F_OK 1 24 | #define R_OK 2 25 | #define W_OK 4 26 | #define X_OK 8 27 | 28 | struct flock { 29 | short l_type; 30 | short l_whence; 31 | off_t l_start; 32 | off_t l_len; 33 | pid_t l_pid; 34 | }; 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/ioctlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__IOCTLVAL_H__ 2 | #define __SYS__IOCTLVAL_H__ 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/signalval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__SIGNALVAL_H__ 2 | #define __SYS__SIGNALVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define SIG_ERR ((__sighandler)(void *)(-1)) 9 | #define SIG_DFL ((__sighandler)(void *)(-2)) 10 | #define SIG_IGN ((__sighandler)(void *)(-3)) 11 | 12 | #define SIGHUP 1 13 | #define SIGINT 2 14 | #define SIGQUIT 3 15 | #define SIGILL 4 16 | #define SIGTRAP 5 17 | #define SIGABRT 6 18 | #define SIGBUS 7 19 | #define SIGFPE 8 20 | #define SIGKILL 9 21 | #define SIGUSR1 10 22 | #define SIGSEGV 11 23 | #define SIGUSR2 12 24 | #define SIGPIPE 13 25 | #define SIGALRM 14 26 | #define SIGTERM 15 27 | #define SIGSTKFLT 16 28 | #define SIGCHLD 17 29 | #define SIGCONT 18 30 | #define SIGSTOP 19 31 | #define SIGTSTP 20 32 | #define SIGTTIN 21 33 | #define SIGTTOU 22 34 | #define SIGURG 23 35 | #define SIGXCPU 24 36 | #define SIGXFSZ 25 37 | #define SIGVTALRM 26 38 | #define SIGPROF 27 39 | #define SIGWINCH 28 40 | #define SIGIO 29 41 | #define SIGPOLL SIGIO 42 | #define SIGPWR 30 43 | #define SIGSYS 31 44 | #define SIGRTMIN 32 45 | #define SIGRTMAX 33 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/statval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__STATVAL_H__ 2 | #define __SYS__STATVAL_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define S_IFMT 0x0F000 11 | #define S_IFBLK 0x06000 12 | #define S_IFCHR 0x02000 13 | #define S_IFIFO 0x01000 14 | #define S_IFREG 0x08000 15 | #define S_IFDIR 0x04000 16 | #define S_IFLNK 0x0A000 17 | #define S_IFSOCK 0x0C000 18 | #define S_IRWXU 0700 19 | #define S_IRUSR 0400 20 | #define S_IWUSR 0200 21 | #define S_IXUSR 0100 22 | #define S_IRWXG 070 23 | #define S_IRGRP 040 24 | #define S_IWGRP 020 25 | #define S_IXGRP 010 26 | #define S_IRWXO 07 27 | #define S_IROTH 04 28 | #define S_IWOTH 02 29 | #define S_IXOTH 01 30 | #define S_ISUID 04000 31 | #define S_ISGID 02000 32 | #define S_ISVTX 01000 33 | #define S_IREAD S_IRUSR 34 | #define S_IWRITE S_IWUSR 35 | #define S_IEXEC S_IXUSR 36 | 37 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 38 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 39 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 40 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 41 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 42 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 43 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 44 | 45 | struct stat { 46 | dev_t st_dev; 47 | ino_t st_ino; 48 | mode_t st_mode; 49 | nlink_t st_nlink; 50 | uid_t st_uid; 51 | gid_t st_gid; 52 | dev_t st_rdev; 53 | off_t st_size; 54 | time_t st_atime; 55 | time_t st_mtime; 56 | time_t st_ctime; 57 | blksize_t st_blksize; 58 | blkcnt_t st_blocks; 59 | }; 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/termiosval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TERMIOSVAL_H__ 2 | #define __SYS__TERMIOSVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef unsigned int cc_t; 9 | typedef unsigned int speed_t; 10 | typedef unsigned int tcflag_t; 11 | 12 | #define NCCS 11 13 | #define VEOF 0 14 | #define VEOL 1 15 | #define VERASE 2 16 | #define VINTR 3 17 | #define VKILL 4 18 | #define VMIN 5 19 | #define VQUIT 6 20 | #define VSTART 7 21 | #define VSTOP 8 22 | #define VSUSP 9 23 | #define VTIME 10 24 | 25 | struct termios { 26 | tcflag_t c_iflag; 27 | tcflag_t c_oflag; 28 | tcflag_t c_cflag; 29 | tcflag_t c_lflag; 30 | cc_t c_cc[NCCS]; 31 | speed_t ibaud; 32 | speed_t obaud; 33 | }; 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/timesval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMESVAL_H__ 2 | #define __SYS__TIMESVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct tms { 9 | clock_t tms_utime; 10 | clock_t tms_stime; 11 | clock_t tms_cutime; 12 | clock_t tms_cstime; 13 | }; 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/timeval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMEVAL_H__ 2 | #define __SYS__TIMEVAL_H__ 3 | 4 | #include 5 | 6 | #define CLOCK_REALTIME 0 7 | #define CLOCK_MONOTONIC 0 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | struct timespec { 14 | time_t tv_sec; 15 | long tv_nsec; 16 | }; 17 | 18 | struct timeval { 19 | time_t tv_sec; 20 | suseconds_t tv_usec; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TYPES_H__ 2 | #define __SYS__TYPES_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef int32_t dev_t; 11 | typedef int32_t ino_t; 12 | typedef int32_t mode_t; 13 | typedef int32_t nlink_t; 14 | typedef int32_t uid_t; 15 | typedef int32_t gid_t; 16 | typedef int32_t time_t; 17 | typedef int32_t suseconds_t; 18 | typedef int32_t blksize_t; 19 | typedef int32_t blkcnt_t; 20 | typedef int32_t pid_t; 21 | typedef int32_t off_t; 22 | typedef int32_t ssize_t; 23 | typedef int32_t clockid_t; 24 | typedef int32_t clock_t; 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /source/ports/i686-echidnaos/sysdeps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int fcntl(int fd, int command, ...) { 14 | // TODO: Implement once echidnaOS supports it. 15 | (void)fd; 16 | (void)command; 17 | return -1; 18 | } 19 | 20 | int open(const char *path, int oflag, ...) { 21 | va_list args; 22 | va_start(args, oflag); 23 | 24 | mode_t mode = 0; 25 | if (oflag & O_CREAT) { 26 | mode = va_arg(args, mode_t); 27 | } 28 | 29 | return OS_open(path, oflag, mode); 30 | } 31 | 32 | int close(int fd) { 33 | return OS_close(fd); 34 | } 35 | 36 | ssize_t read(int fd, void *buf, size_t count) { 37 | return (ssize_t)OS_read(fd, buf, count); 38 | } 39 | 40 | ssize_t write(int fd, const void *buf, size_t count) { 41 | return (ssize_t)OS_write(fd, buf, count); 42 | } 43 | 44 | char *getcwd(char *buffer, size_t size) { 45 | (void)size; 46 | OS_pwd(buffer); 47 | return buffer; 48 | } 49 | 50 | int rmdir(const char *path) { 51 | return OS_vfs_remove(path); 52 | } 53 | 54 | int unlink(const char *path) { 55 | return OS_vfs_remove(path); 56 | } 57 | 58 | int fork(void) { 59 | pid_t ret; 60 | asm volatile ("int $0x80" 61 | : "=a"(ret) 62 | : "a"(0x05) 63 | : "edx", "memory"); 64 | return ret; 65 | } 66 | 67 | void _exit(int error_code) { 68 | int discard; 69 | asm volatile ("int $0x80" 70 | : "=a"(discard) 71 | : "a"(0x00), "c"(error_code) 72 | : "edx", "memory" 73 | ); 74 | } 75 | 76 | off_t lseek(int fd, off_t offset, int whence) { 77 | int return_val; 78 | asm volatile ( "movl $0x2e, %%eax\n\t" 79 | "int $0x80\n\t" 80 | : "=a" (return_val) 81 | : "c" (fd), 82 | "d" (offset), 83 | "D" (whence) 84 | : ); 85 | return return_val; 86 | } 87 | 88 | void *sbrk(intptr_t size) { 89 | size_t ptr = OS_get_heap_base() + OS_get_heap_size(); 90 | if (OS_resize_heap(OS_get_heap_size() + size) == -1) { 91 | errno = ENOMEM; 92 | return (void *)-1; 93 | } 94 | return (void *)ptr; 95 | } 96 | 97 | int stat(const char *path, struct stat *result) { 98 | vfs_metadata_t metadata; 99 | 100 | if (OS_vfs_get_metadata(path, &metadata, VFS_FILE_TYPE) == VFS_FAILURE) { 101 | if (OS_vfs_get_metadata(path, &metadata, VFS_DIRECTORY_TYPE) == VFS_FAILURE) { 102 | if (OS_vfs_get_metadata(path, &metadata, VFS_DEVICE_TYPE) == VFS_FAILURE) { 103 | return ENOENT; 104 | } else { 105 | result->st_mode = S_IFBLK; 106 | } 107 | } else { 108 | result->st_mode = S_IFDIR; 109 | } 110 | } else { 111 | result->st_mode = S_IFREG; 112 | } 113 | 114 | result->st_dev = 0; 115 | result->st_ino = 0; 116 | result->st_nlink = 0; 117 | result->st_uid = 0; 118 | result->st_gid = 0; 119 | result->st_rdev = 0; 120 | result->st_size = metadata.size; 121 | result->st_atime = 0; 122 | result->st_mtime = 0; 123 | result->st_ctime = 0; 124 | result->st_blksize = 32768; 125 | result->st_blocks = metadata.size / 32768 + 1; 126 | 127 | return 0; 128 | } 129 | 130 | int fstat(int fd, struct stat *result) { 131 | // TODO: Implement when echidnaOS supports it. 132 | (void)fd; 133 | (void)result; 134 | assert(!"This is a stub"); 135 | return -1; 136 | } 137 | 138 | int clock_gettime(clockid_t clock_id, struct timespec *tp) { 139 | // TODO: Implement this once echidnaOS supports it. 140 | (void)clock_id; 141 | (void)tp; 142 | return -1; 143 | } 144 | 145 | int sched_yield(void) { 146 | // TODO: Implement this once echidnaOS has it, if ever. 147 | return -1; 148 | } 149 | 150 | int access(const char *path, int amode) { 151 | (void)amode; 152 | 153 | int fd = open(path, O_RDWR); 154 | if (fd == -1) { 155 | return -1; 156 | } 157 | 158 | close(fd); 159 | return 0; 160 | } 161 | 162 | int pipe(int fds[2]) { 163 | // TODO: Implement when echidnaOS supports it. 164 | (void)fds; 165 | assert(!"This is a stub"); 166 | return -1; 167 | } 168 | 169 | pid_t getpid(void) { 170 | pid_t pid; 171 | asm volatile ( 172 | "int $0x80" 173 | : "=a"(pid) 174 | : "a"(0x15) 175 | : "edx", "memory" 176 | ); 177 | return pid; 178 | } 179 | 180 | pid_t getppid(void) { 181 | // TODO: Implement when echidnaOS supports it. 182 | assert(!"This is a stub"); 183 | return 0; 184 | } 185 | 186 | pid_t getpgrp(void) { 187 | // TODO: Implement when echidnaOS supports it. 188 | assert(!"This is a stub"); 189 | return 0; 190 | } 191 | 192 | gid_t getgid(void) { 193 | // TODO: Implement when echidnaOS supports it. 194 | assert(!"This is a stub"); 195 | return 0; 196 | } 197 | 198 | int setgid(gid_t gid) { 199 | // TODO: Implement when echidnaOS supports it. 200 | (void)gid; 201 | assert(!"This is a stub"); 202 | return -1; 203 | } 204 | 205 | gid_t getegid(void) { 206 | // TODO: Implement when echidnaOS supports it. 207 | assert(!"This is a stub"); 208 | return 0; 209 | } 210 | 211 | uid_t getuid(void) { 212 | // TODO: Implement when echidnaOS supports it. 213 | assert(!"This is a stub"); 214 | return 0; 215 | } 216 | 217 | int setuid(uid_t uid) { 218 | // TODO: Implement when echidnaOS supports it. 219 | (void)uid; 220 | assert(!"This is a stub"); 221 | return -1; 222 | } 223 | 224 | uid_t geteuid(void) { 225 | // TODO: Implement when echidnaOS supports it. 226 | assert(!"This is a stub"); 227 | return 0; 228 | } 229 | 230 | int execve(const char *path, char *const argv[], char *const envp[]) { 231 | int discard1, discard2; 232 | 233 | asm volatile ( 234 | "int $0x80" 235 | : "=a"(discard1), "=d"(discard2) 236 | : "a"(0x03), "c"(path), "d"(argv), "D"(envp) 237 | : "memory" 238 | ); 239 | 240 | return EIO; 241 | } 242 | 243 | int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { 244 | // TODO: Implement when echidnaOS supports it. 245 | (void)rqtp; 246 | (void)rmtp; 247 | assert(!"This is a stub"); 248 | return -1; 249 | } 250 | 251 | int ttyname_r(int fd, char *name, size_t namesize) { 252 | // TODO: Implement when echidnaOS supports it. 253 | (void)fd; 254 | (void)name; 255 | (void)namesize; 256 | assert(!"This is a stub"); 257 | return -1; 258 | } 259 | 260 | unsigned alarm(unsigned seconds) { 261 | // TODO: Implement when echidnaOS supports it. 262 | (void)seconds; 263 | assert(!"This is a stub"); 264 | return 0; 265 | } 266 | 267 | int kill(pid_t pid, int signal) { 268 | // TODO: Implement when echidnaOS supports it. 269 | (void)pid; 270 | (void)signal; 271 | assert(!"This is a stub"); 272 | return -1; 273 | } 274 | 275 | int ioctl(int fd, int request, ...) { 276 | // TODO: Implement when echidnaOS supports it. 277 | (void)fd; 278 | (void)request; 279 | assert(!"This is a stub"); 280 | return -1; 281 | } 282 | 283 | int tcgetattr(int fd, struct termios *result) { 284 | // TODO: Implement when echidnaOS supports it. 285 | (void)fd; 286 | (void)result; 287 | assert(!"This is a stub"); 288 | return -1; 289 | } 290 | 291 | int tcsetattr(int fd, int action, const struct termios *result) { 292 | // TODO: Implement when echidnaOS supports it. 293 | (void)fd; 294 | (void)action; 295 | (void)result; 296 | assert(!"This is a stub"); 297 | return -1; 298 | } 299 | 300 | int tcflow(int fd, int action) { 301 | // TODO: Implement when echidnaOS supports it. 302 | (void)fd; 303 | (void)action; 304 | assert(!"This is a stub"); 305 | return -1; 306 | } 307 | 308 | int fchmod(int fd, mode_t mode) { 309 | // TODO: Implement when echidnaOS supports it. 310 | (void)fd; 311 | (void)mode; 312 | assert(!"This is a stub"); 313 | return -1; 314 | } 315 | 316 | clock_t times(struct tms *t) { 317 | // TODO: Implement when echidnaOS supports it. 318 | (void)t; 319 | assert(!"This is a stub"); 320 | return (clock_t)-1; 321 | } 322 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/crt0.S: -------------------------------------------------------------------------------- 1 | .section .text 2 | .globl _start 3 | _start: 4 | xor %ebp, %ebp // Mark the end of stack frames 5 | mov (%rsp), %edi // Get argc from the stack 6 | lea 8(%rsp), %rsi // Take the address of argv from the stack 7 | lea 16(%rsp,%rdi,8), %rdx // Take the address of envp from the stack 8 | xor %eax, %eax // Per ABI and compatibility with icc 9 | call __slibc_init // Hand it off to the libc. 10 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/siglist.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int sys_nsig = 30; 4 | 5 | const char *const sys_siglist[] = { 6 | [SIGHUP] = "Hangup", 7 | [SIGINT] = "Terminal interrupt signal", 8 | [SIGQUIT] = "Terminal quit signal", 9 | [SIGILL] = "Illegal instruction", 10 | [SIGTRAP] = "Trace/breakpoint trap", 11 | [SIGABRT] = "Process abort signal", 12 | [SIGBUS] = "Access to an undefined portion of a memory object", 13 | [SIGFPE] = "Erroneous arithmetic operation", 14 | [SIGKILL] = "Kill (cannot be caught or ignored)", 15 | [SIGUSR1] = "User-defined signal 1", 16 | [SIGSEGV] = "Invalid memory reference", 17 | [SIGUSR2] = "User-defined signal 2", 18 | [SIGPIPE] = "Write on a pipe with no one to read it", 19 | [SIGTERM] = "Termination signal", 20 | [SIGSTKFLT] = "Stack fault", 21 | [SIGCHLD] = "Child process terminated, stopped", 22 | [SIGCONT] = "Continue executing, if stopped", 23 | [SIGSTOP] = "Stop executing (cannot be caught or ignored)", 24 | [SIGTSTP] = "Terminal stop signal", 25 | [SIGTTIN] = "Background process attempting read", 26 | [SIGTTOU] = "Background process attempting write", 27 | [SIGURG] = "High bandwidth data is available at a socket", 28 | [SIGXCPU] = "CPU time limit exceeded", 29 | [SIGXFSZ] = "File size limit exceeded", 30 | [SIGVTALRM] = "Virtual timer expired", 31 | [SIGPROF] = "Profiling timer expired", 32 | [SIGWINCH] = "Window size change", 33 | [SIGPOLL] = "Pollable event", 34 | [SIGPWR] = "Power failure restart", 35 | [SIGSYS] = "Bad system call" 36 | }; 37 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/errnoval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__ERRNOVAL_H__ 2 | #define __SYS__ERRNOVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // All of them shamelessly copied from 9 | // https://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html 10 | // Give them a hug on my behalf. 11 | 12 | #define EPERM 1 /* Operation not permitted */ 13 | #define ENOENT 2 /* No such file or directory */ 14 | #define ESRCH 3 /* No such process */ 15 | #define EINTR 4 /* Interrupted system call */ 16 | #define EIO 5 /* I/O error */ 17 | #define ENXIO 6 /* No such device or address */ 18 | #define E2BIG 7 /* Arg list too long */ 19 | #define ENOEXEC 8 /* Exec format error */ 20 | #define EBADF 9 /* Bad file number */ 21 | #define ECHILD 10 /* No child processes */ 22 | #define EAGAIN 11 /* Try again */ 23 | #define ENOMEM 12 /* Out of memory */ 24 | #define EACCES 13 /* Permission denied */ 25 | #define EFAULT 14 /* Bad address */ 26 | #define ENOTBLK 15 /* Block device required */ 27 | #define EBUSY 16 /* Device or resource busy */ 28 | #define EEXIST 17 /* File exists */ 29 | #define EXDEV 18 /* Cross-device link */ 30 | #define ENODEV 19 /* No such device */ 31 | #define ENOTDIR 20 /* Not a directory */ 32 | #define EISDIR 21 /* Is a directory */ 33 | #define EINVAL 22 /* Invalid argument */ 34 | #define ENFILE 23 /* File table overflow */ 35 | #define EMFILE 24 /* Too many open files */ 36 | #define ENOTTY 25 /* Not a typewriter */ 37 | #define ETXTBSY 26 /* Text file busy */ 38 | #define EFBIG 27 /* File too large */ 39 | #define ENOSPC 28 /* No space left on device */ 40 | #define ESPIPE 29 /* Illegal seek */ 41 | #define EROFS 30 /* Read-only file system */ 42 | #define EMLINK 31 /* Too many links */ 43 | #define EPIPE 32 /* Broken pipe */ 44 | #define EDOM 33 /* Math argument out of domain of func */ 45 | #define ERANGE 34 /* Math result not representable */ 46 | #define EDEADLK 35 /* Resource deadlock would occur */ 47 | #define ENAMETOOLONG 36 /* File name too long */ 48 | #define ENOLCK 37 /* No record locks available */ 49 | #define ENOSYS 38 /* Function not implemented */ 50 | #define ENOTEMPTY 39 /* Directory not empty */ 51 | #define ELOOP 40 /* Too many symbolic links encountered */ 52 | #define EWOULDBLOCK EAGAIN /* Operation would block */ 53 | #define ENOMSG 42 /* No message of desired type */ 54 | #define EIDRM 43 /* Identifier removed */ 55 | #define ECHRNG 44 /* Channel number out of range */ 56 | #define EL2NSYNC 45 /* Level 2 not synchronized */ 57 | #define EL3HLT 46 /* Level 3 halted */ 58 | #define EL3RST 47 /* Level 3 reset */ 59 | #define ELNRNG 48 /* Link number out of range */ 60 | #define EUNATCH 49 /* Protocol driver not attached */ 61 | #define ENOCSI 50 /* No CSI structure available */ 62 | #define EL2HLT 51 /* Level 2 halted */ 63 | #define EBADE 52 /* Invalid exchange */ 64 | #define EBADR 53 /* Invalid request descriptor */ 65 | #define EXFULL 54 /* Exchange full */ 66 | #define ENOANO 55 /* No anode */ 67 | #define EBADRQC 56 /* Invalid request code */ 68 | #define EBADSLT 57 /* Invalid slot */ 69 | #define EDEADLOCK EDEADLK 70 | #define EBFONT 59 /* Bad font file format */ 71 | #define ENOSTR 60 /* Device not a stream */ 72 | #define ENODATA 61 /* No data available */ 73 | #define ETIME 62 /* Timer expired */ 74 | #define ENOSR 63 /* Out of streams resources */ 75 | #define ENONET 64 /* Machine is not on the network */ 76 | #define ENOPKG 65 /* Package not installed */ 77 | #define EREMOTE 66 /* Object is remote */ 78 | #define ENOLINK 67 /* Link has been severed */ 79 | #define EADV 68 /* Advertise error */ 80 | #define ESRMNT 69 /* Srmount error */ 81 | #define ECOMM 70 /* Communication error on send */ 82 | #define EPROTO 71 /* Protocol error */ 83 | #define EMULTIHOP 72 /* Multihop attempted */ 84 | #define EDOTDOT 73 /* RFS specific error */ 85 | #define EBADMSG 74 /* Not a data message */ 86 | #define EOVERFLOW 75 /* Value too large for defined data type */ 87 | #define ENOTUNIQ 76 /* Name not unique on network */ 88 | #define EBADFD 77 /* File descriptor in bad state */ 89 | #define EREMCHG 78 /* Remote address changed */ 90 | #define ELIBACC 79 /* Can not access a needed shared library */ 91 | #define ELIBBAD 80 /* Accessing a corrupted shared library */ 92 | #define ELIBSCN 81 /* .lib section in a.out corrupted */ 93 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ 94 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */ 95 | #define EILSEQ 84 /* Illegal byte sequence */ 96 | #define ERESTART 85 /* Interrupted system call should be restarted */ 97 | #define ESTRPIPE 86 /* Streams pipe error */ 98 | #define EUSERS 87 /* Too many users */ 99 | #define ENOTSOCK 88 /* Socket operation on non-socket */ 100 | #define EDESTADDRREQ 89 /* Destination address required */ 101 | #define EMSGSIZE 90 /* Message too long */ 102 | #define EPROTOTYPE 91 /* Protocol wrong type for socket */ 103 | #define ENOPROTOOPT 92 /* Protocol not available */ 104 | #define EPROTONOSUPPORT 93 /* Protocol not supported */ 105 | #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ 106 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 107 | #define ENOTSUPP EOPNOTSUPP 108 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ 109 | #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ 110 | #define EADDRINUSE 98 /* Address already in use */ 111 | #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ 112 | #define ENETDOWN 100 /* Network is down */ 113 | #define ENETUNREACH 101 /* Network is unreachable */ 114 | #define ENETRESET 102 /* Network dropped connection because of reset */ 115 | #define ECONNABORTED 103 /* Software caused connection abort */ 116 | #define ECONNRESET 104 /* Connection reset by peer */ 117 | #define ENOBUFS 105 /* No buffer space available */ 118 | #define EISCONN 106 /* Transport endpoint is already connected */ 119 | #define ENOTCONN 107 /* Transport endpoint is not connected */ 120 | #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ 121 | #define ETOOMANYREFS 109 /* Too many references: cannot splice */ 122 | #define ETIMEDOUT 110 /* Connection timed out */ 123 | #define ECONNREFUSED 111 /* Connection refused */ 124 | #define EHOSTDOWN 112 /* Host is down */ 125 | #define EHOSTUNREACH 113 /* No route to host */ 126 | #define EALREADY 114 /* Operation already in progress */ 127 | #define EINPROGRESS 115 /* Operation now in progress */ 128 | #define ESTALE 116 /* Stale NFS file handle */ 129 | #define EUCLEAN 117 /* Structure needs cleaning */ 130 | #define ENOTNAM 118 /* Not a XENIX named type file */ 131 | #define ENAVAIL 119 /* No XENIX semaphores available */ 132 | #define EISNAM 120 /* Is a named type file */ 133 | #define EREMOTEIO 121 /* Remote I/O error */ 134 | #define EDQUOT 122 /* Quota exceeded */ 135 | #define ENOMEDIUM 123 /* No medium found */ 136 | #define EMEDIUMTYPE 124 /* Wrong medium type */ 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/fcntlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__FCNTLVAL_H__ 2 | #define __SYS__FCNTLVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define O_ACCMODE 00000003 9 | #define O_RDONLY 00000000 10 | #define O_WRONLY 00000001 11 | #define O_RDWR 00000002 12 | #define O_CREAT 00000100 13 | #define O_EXCL 00000200 14 | #define O_NOCTTY 00000400 15 | #define O_TRUNC 00001000 16 | #define O_APPEND 00002000 17 | #define O_NONBLOCK 00004000 18 | #define O_DSYNC 00010000 /* used to be O_SYNC, see below */ 19 | #define FASYNC 00020000 /* fcntl, for BSD compatibility */ 20 | #define O_DIRECT 00040000 /* direct disk access hint */ 21 | #define O_LARGEFILE 00100000 22 | #define O_DIRECTORY 00200000 /* must be a directory */ 23 | #define O_NOFOLLOW 00400000 /* don't follow links */ 24 | #define O_NOATIME 01000000 25 | #define O_CLOEXEC 02000000 /* set close_on_exec */ 26 | /* 27 | * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using 28 | * the O_SYNC flag. We continue to use the existing numerical value 29 | * for O_DSYNC semantics now, but using the correct symbolic name for it. 30 | * This new value is used to request true Posix O_SYNC semantics. It is 31 | * defined in this strange way to make sure applications compiled against 32 | * new headers get at least O_DSYNC semantics on older kernels. 33 | * 34 | * This has the nice side-effect that we can simply test for O_DSYNC 35 | * wherever we do not care if O_DSYNC or O_SYNC is used. 36 | * 37 | * Note: __O_SYNC must never be used directly. 38 | */ 39 | #ifndef O_SYNC 40 | #define __O_SYNC 04000000 41 | #define O_SYNC (__O_SYNC|O_DSYNC) 42 | #endif 43 | 44 | #ifndef O_PATH 45 | #define O_PATH 010000000 46 | #endif 47 | 48 | #ifndef __O_TMPFILE 49 | #define __O_TMPFILE 020000000 50 | #endif 51 | 52 | /* a horrid kludge trying to make sure that this will fail on old kernels */ 53 | #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) 54 | #define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT) 55 | 56 | #ifndef O_NDELAY 57 | #define O_NDELAY O_NONBLOCK 58 | #endif 59 | 60 | #define SEEK_SET 0 61 | #define SEEK_END 2 62 | #define SEEK_CUR 1 63 | 64 | #define F_DUPFD 0 65 | #define F_GETFD 1 66 | #define F_SETFD 2 67 | #define F_GETFL 3 68 | #define F_SETFL 4 69 | #define F_SETOWN 8 70 | #define F_GETOWN 9 71 | #define F_SETSIG 10 72 | #define F_GETSIG 11 73 | 74 | #define F_OK 0 75 | #define R_OK 4 76 | #define W_OK 2 77 | #define X_OK 1 78 | 79 | struct flock { 80 | short l_type; 81 | short l_whence; 82 | off_t l_start; 83 | off_t l_len; 84 | pid_t l_pid; 85 | }; 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/ioctlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__IOCTLVAL_H__ 2 | #define __SYS__IOCTLVAL_H__ 3 | 4 | #define TCGETS 0x5401 5 | #define TCSETS 0x5402 6 | #define TCXONC 0x540A 7 | #define TIOCGWINSZ 0x5413 8 | #define TIOCSWINSZ 0x5414 9 | 10 | struct winsize { 11 | unsigned short ws_row; 12 | unsigned short ws_col; 13 | unsigned short ws_xpixel; 14 | unsigned short ws_ypixel; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/signalval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__SIGNALVAL_H__ 2 | #define __SYS__SIGNALVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define SIG_ERR ((void (*)(int))-1) 9 | #define SIG_DFL ((void (*)(int)) 0) 10 | #define SIG_IGN ((void (*)(int)) 1) 11 | 12 | #define SIGHUP 1 13 | #define SIGINT 2 14 | #define SIGQUIT 3 15 | #define SIGILL 4 16 | #define SIGTRAP 5 17 | #define SIGABRT 6 18 | #define SIGIOT SIGABRT 19 | #define SIGBUS 7 20 | #define SIGFPE 8 21 | #define SIGKILL 9 22 | #define SIGUSR1 10 23 | #define SIGSEGV 11 24 | #define SIGUSR2 12 25 | #define SIGPIPE 13 26 | #define SIGALRM 14 27 | #define SIGTERM 15 28 | #define SIGSTKFLT 16 29 | #define SIGCHLD 17 30 | #define SIGCONT 18 31 | #define SIGSTOP 19 32 | #define SIGTSTP 20 33 | #define SIGTTIN 21 34 | #define SIGTTOU 22 35 | #define SIGURG 23 36 | #define SIGXCPU 24 37 | #define SIGXFSZ 25 38 | #define SIGVTALRM 26 39 | #define SIGPROF 27 40 | #define SIGWINCH 28 41 | #define SIGIO 29 42 | #define SIGPOLL 29 43 | #define SIGPWR 30 44 | #define SIGSYS 31 45 | #define SIGUNUSED SIGSYS 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/statval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__STATVAL_H__ 2 | #define __SYS__STATVAL_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define S_IFMT 0170000 12 | #define S_IFDIR 0040000 13 | #define S_IFCHR 0020000 14 | #define S_IFBLK 0060000 15 | #define S_IFREG 0100000 16 | #define S_IFIFO 0010000 17 | #define S_IFLNK 0120000 18 | #define S_IFSOCK 0140000 19 | #define S_ISUID 04000 20 | #define S_ISGID 02000 21 | #define S_ISVTX 01000 22 | #define S_IRUSR 0400 23 | #define S_IWUSR 0200 24 | #define S_IXUSR 0100 25 | #define S_IRWXU 0700 26 | #define S_IRGRP 0040 27 | #define S_IWGRP 0020 28 | #define S_IXGRP 0010 29 | #define S_IRWXG 0070 30 | #define S_IROTH 0004 31 | #define S_IWOTH 0002 32 | #define S_IXOTH 0001 33 | #define S_IRWXO 0007 34 | 35 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 36 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 37 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 38 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 39 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 40 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 41 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 42 | 43 | #define st_atime st_atim.tv_sec 44 | #define st_mtime st_mtim.tv_sec 45 | #define st_ctime st_ctim.tv_sec 46 | 47 | struct stat { 48 | dev_t st_dev; 49 | ino_t st_ino; 50 | nlink_t st_nlink; 51 | mode_t st_mode; 52 | uid_t st_uid; 53 | gid_t st_gid; 54 | uint32_t __pad0; 55 | dev_t st_rdev; 56 | off_t st_size; 57 | blksize_t st_blksize; 58 | blkcnt_t st_blocks; 59 | struct timespec st_atim; 60 | struct timespec st_mtim; 61 | struct timespec st_ctim; 62 | long __unused[3]; 63 | }; 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/termiosval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TERMIOSVAL_H__ 2 | #define __SYS__TERMIOSVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define NCCS 32 9 | #define VINTR 0 10 | #define VQUIT 1 11 | #define VERASE 2 12 | #define VKILL 3 13 | #define VEOF 4 14 | #define VTIME 5 15 | #define VMIN 6 16 | #define VSWTC 7 17 | #define VSTART 8 18 | #define VSTOP 9 19 | #define VSUSP 10 20 | #define VEOL 11 21 | #define VREPRINT 12 22 | #define VDISCARD 13 23 | #define VWERASE 14 24 | #define VLNEXT 15 25 | #define VEOL2 16 26 | 27 | typedef unsigned char cc_t; 28 | typedef unsigned int speed_t; 29 | typedef unsigned int tcflag_t; 30 | 31 | struct termios { 32 | tcflag_t c_iflag; 33 | tcflag_t c_oflag; 34 | tcflag_t c_cflag; 35 | tcflag_t c_lflag; 36 | cc_t c_line; 37 | cc_t c_cc[NCCS]; 38 | speed_t __c_ispeed; 39 | speed_t __c_ospeed; 40 | }; 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/timesval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMESVAL_H__ 2 | #define __SYS__TIMESVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct tms { 9 | clock_t tms_utime; 10 | clock_t tms_stime; 11 | clock_t tms_cutime; 12 | clock_t tms_cstime; 13 | }; 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/timeval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMEVAL_H__ 2 | #define __SYS__TIMEVAL_H__ 3 | 4 | #include 5 | 6 | #define CLOCK_REALTIME 0 7 | #define CLOCK_MONOTONIC 1 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | struct timespec { 14 | time_t tv_sec; 15 | long tv_nsec; 16 | }; 17 | 18 | struct timeval { 19 | time_t tv_sec; 20 | suseconds_t tv_usec; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TYPES_H__ 2 | #define __SYS__TYPES_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef uint64_t dev_t; 11 | typedef uint64_t ino_t; 12 | typedef uint32_t mode_t; 13 | typedef uint64_t nlink_t; 14 | typedef uint32_t uid_t; 15 | typedef uint32_t gid_t; 16 | typedef int64_t time_t; 17 | typedef int64_t suseconds_t; 18 | typedef int64_t blksize_t; 19 | typedef int64_t blkcnt_t; 20 | typedef int32_t pid_t; 21 | typedef int64_t off_t; 22 | typedef int64_t ssize_t; 23 | typedef int32_t clockid_t; 24 | typedef int64_t clock_t; 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /source/ports/x86_64-linux/sysdeps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define LINUX_SYSCALL(ret, syscall) do { \ 14 | __asm__ __volatile__ ( \ 15 | "syscall": "=a"(ret) : "a"(syscall) : "rcx", "r11", "memory" \ 16 | ); \ 17 | } while (0) 18 | 19 | #define LINUX_SYSCALL1(ret, syscall, arg1) do { \ 20 | __asm__ __volatile__ ( \ 21 | "syscall": "=a"(ret) : "a"(syscall), "D"(arg1) : "rcx", "r11", "memory" \ 22 | ); \ 23 | } while (0) 24 | 25 | #define LINUX_SYSCALL1_NORET(syscall, arg1) do { \ 26 | __asm__ __volatile__ ( \ 27 | "syscall": : "a"(syscall), "D"(arg1) : "rcx", "r11", "memory" \ 28 | ); \ 29 | } while (0) 30 | 31 | #define LINUX_SYSCALL2(ret, syscall, arg1, arg2) do { \ 32 | __asm__ __volatile__ ( \ 33 | "syscall": "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2) \ 34 | : "rcx", "r11", "memory" \ 35 | ); \ 36 | } while (0) 37 | 38 | #define LINUX_SYSCALL3(ret, syscall, arg1, arg2, arg3) do { \ 39 | __asm__ __volatile__ ( \ 40 | "syscall": "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) \ 41 | : "rcx", "r11", "memory" \ 42 | ); \ 43 | } while (0) 44 | 45 | int fcntl(int fd, int command, ...) { 46 | va_list args; 47 | va_start(args, command); 48 | uint64_t arg = va_arg(args, uint64_t); 49 | 50 | int ret; 51 | LINUX_SYSCALL3(ret, 72, fd, command, arg); 52 | 53 | if (ret < 0) { 54 | errno = -ret; 55 | va_end(args); 56 | return -1; 57 | } 58 | 59 | va_end(args); 60 | return ret; 61 | } 62 | 63 | int open(const char *path, int oflag, ...) { 64 | va_list args; 65 | va_start(args, oflag); 66 | 67 | mode_t mode = 0; 68 | if (oflag & (O_CREAT | O_TMPFILE)) { 69 | mode = va_arg(args, mode_t); 70 | } 71 | 72 | ssize_t ret; 73 | LINUX_SYSCALL3(ret, 2, path, oflag, mode); 74 | 75 | if (ret < 0) { 76 | errno = -ret; 77 | va_end(args); 78 | return -1; 79 | } 80 | 81 | va_end(args); 82 | return ret; 83 | } 84 | 85 | int close(int fd) { 86 | ssize_t ret; 87 | LINUX_SYSCALL1(ret, 3, fd); 88 | 89 | if (ret < 0) { 90 | errno = -ret; 91 | return -1; 92 | } 93 | 94 | return ret; 95 | } 96 | 97 | ssize_t read(int fd, void *buf, size_t count) { 98 | ssize_t ret; 99 | LINUX_SYSCALL3(ret, 0, fd, buf, count); 100 | 101 | if (ret < 0) { 102 | errno = -ret; 103 | return -1; 104 | } 105 | 106 | return ret; 107 | } 108 | 109 | ssize_t write(int fd, const void *buf, size_t count) { 110 | ssize_t ret; 111 | LINUX_SYSCALL3(ret, 1, fd, buf, count); 112 | 113 | if (ret < 0) { 114 | errno = -ret; 115 | return -1; 116 | } 117 | 118 | return ret; 119 | } 120 | 121 | char *getcwd(char *buf, size_t size) { 122 | ssize_t ret; 123 | LINUX_SYSCALL2(ret, 79, buf, size); 124 | 125 | if (ret < 0) { 126 | errno = -ret; 127 | return NULL; 128 | } 129 | 130 | return buf; 131 | } 132 | 133 | int rmdir(const char *path) { 134 | ssize_t ret; 135 | LINUX_SYSCALL1(ret, 84, path); 136 | 137 | if (ret < 0) { 138 | errno = -ret; 139 | return -1; 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | int unlink(const char *path) { 146 | ssize_t ret; 147 | LINUX_SYSCALL1(ret, 87, path); 148 | 149 | if (ret < 0) { 150 | errno = -ret; 151 | return -1; 152 | } 153 | 154 | return 0; 155 | } 156 | 157 | pid_t fork(void) { 158 | pid_t ret; 159 | LINUX_SYSCALL(ret, 57); 160 | 161 | if (ret < 0) { 162 | errno = -ret; 163 | } 164 | 165 | return ret; 166 | } 167 | 168 | void _exit(int error_code) { 169 | LINUX_SYSCALL1_NORET(60, error_code); 170 | } 171 | 172 | off_t lseek(int fd, off_t offset, int whence) { 173 | off_t ret; 174 | LINUX_SYSCALL3(ret, 8, fd, offset, whence); 175 | 176 | if (ret < 0) { 177 | errno = -ret; 178 | } 179 | 180 | return ret; 181 | } 182 | 183 | static intptr_t __base_brk = -1; 184 | 185 | void *sbrk(intptr_t increment) { 186 | intptr_t current_brk; 187 | LINUX_SYSCALL1(current_brk, 12, NULL); 188 | 189 | if (__base_brk == -1) { 190 | __base_brk = current_brk; 191 | } 192 | 193 | intptr_t new_brk = current_brk + increment; 194 | if (new_brk < __base_brk) { 195 | errno = ENOMEM; 196 | return (void*)-1; 197 | } 198 | 199 | int ret; 200 | LINUX_SYSCALL1(ret, 12, new_brk); 201 | if (ret < 0) { 202 | errno = -ret; 203 | return (void*)-1; 204 | } 205 | 206 | return (void*)current_brk; 207 | } 208 | 209 | int stat(const char *path, struct stat *result) { 210 | int ret; 211 | LINUX_SYSCALL2(ret, 4, path, result); 212 | 213 | if (ret < 0) { 214 | errno = -ret; 215 | } 216 | 217 | return ret; 218 | } 219 | 220 | int fstat(int fd, struct stat *result) { 221 | int ret; 222 | LINUX_SYSCALL2(ret, 5, fd, result); 223 | 224 | if (ret < 0) { 225 | errno = -ret; 226 | } 227 | 228 | return ret; 229 | } 230 | 231 | int clock_gettime(clockid_t clock_id, struct timespec *tp) { 232 | int ret; 233 | LINUX_SYSCALL2(ret, 228, clock_id, tp); 234 | 235 | if (ret < 0) { 236 | errno = -ret; 237 | return -1; 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | int sched_yield(void) { 244 | int ret; 245 | LINUX_SYSCALL(ret, 24); 246 | 247 | if (ret < 0) { 248 | errno = -ret; 249 | return -1; 250 | } 251 | 252 | return 0; 253 | } 254 | 255 | int access(const char *path, int amode) { 256 | int ret; 257 | LINUX_SYSCALL2(ret, 24, path, amode); 258 | 259 | if (ret < 0) { 260 | errno = -ret; 261 | return -1; 262 | } 263 | 264 | return 0; 265 | } 266 | 267 | int pipe(int fds[2]) { 268 | int ret; 269 | LINUX_SYSCALL1(ret, 24, fds); 270 | 271 | if (ret < 0) { 272 | errno = -ret; 273 | return -1; 274 | } 275 | 276 | return 0; 277 | } 278 | 279 | pid_t getpid(void) { 280 | pid_t ret; 281 | LINUX_SYSCALL(ret, 39); 282 | return ret; 283 | } 284 | 285 | pid_t getppid(void) { 286 | pid_t ret; 287 | LINUX_SYSCALL(ret, 110); 288 | return ret; 289 | } 290 | 291 | pid_t getpgrp(void) { 292 | pid_t ret; 293 | LINUX_SYSCALL(ret, 111); 294 | return ret; 295 | } 296 | 297 | gid_t getgid(void) { 298 | gid_t ret; 299 | LINUX_SYSCALL(ret, 104); 300 | return ret; 301 | } 302 | 303 | int setgid(gid_t gid) { 304 | int ret; 305 | LINUX_SYSCALL1(ret, 106, gid); 306 | 307 | if (ret < 0) { 308 | errno = -ret; 309 | return -1; 310 | } 311 | 312 | return 0; 313 | } 314 | 315 | gid_t getegid(void) { 316 | gid_t ret; 317 | LINUX_SYSCALL(ret, 108); 318 | return ret; 319 | } 320 | 321 | uid_t getuid(void) { 322 | uid_t ret; 323 | LINUX_SYSCALL(ret, 102); 324 | return ret; 325 | } 326 | 327 | int setuid(uid_t uid) { 328 | int ret; 329 | LINUX_SYSCALL1(ret, 105, uid); 330 | 331 | if (ret < 0) { 332 | errno = -ret; 333 | return -1; 334 | } 335 | 336 | return 0; 337 | } 338 | 339 | uid_t geteuid(void) { 340 | uid_t ret; 341 | LINUX_SYSCALL(ret, 107); 342 | return ret; 343 | } 344 | 345 | int execve(const char *path, char *const argv[], char *const envp[]) { 346 | int ret; 347 | LINUX_SYSCALL3(ret, 59, path, argv, envp); 348 | 349 | if (ret < 0) { 350 | errno = -ret; 351 | return -1; 352 | } 353 | 354 | return ret; 355 | } 356 | 357 | int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { 358 | int ret; 359 | LINUX_SYSCALL2(ret, 35, rqtp, rmtp); 360 | 361 | if (ret < 0) { 362 | errno = -ret; 363 | return -1; 364 | } 365 | 366 | return 0; 367 | } 368 | 369 | int ttyname_r(int fd, char *name, size_t namesize) { 370 | // TODO: Implement when we have the will to do so. 371 | (void)fd; 372 | (void)name; 373 | (void)namesize; 374 | assert(!"This is a stub"); 375 | return -1; 376 | } 377 | 378 | unsigned alarm(unsigned seconds) { 379 | int ret; 380 | LINUX_SYSCALL1(ret, 37, seconds); 381 | return ret; 382 | } 383 | 384 | int kill(pid_t pid, int signal) { 385 | int ret; 386 | LINUX_SYSCALL2(ret, 62, pid, signal); 387 | 388 | if (ret < 0) { 389 | errno = -ret; 390 | return -1; 391 | } 392 | 393 | return 0; 394 | } 395 | 396 | int ioctl(int fd, int request, ...) { 397 | va_list args; 398 | va_start(args, request); 399 | void *arg = va_arg(args, void *); 400 | va_end(args); 401 | 402 | int ret; 403 | LINUX_SYSCALL3(ret, 16, fd, request, arg); 404 | 405 | if (ret < 0) { 406 | errno = -ret; 407 | return -1; 408 | } 409 | 410 | return ret; 411 | } 412 | 413 | int tcgetattr(int fd, struct termios *result) { 414 | if (ioctl(fd, TCGETS, result)) { 415 | return -1; 416 | } 417 | 418 | return 0; 419 | } 420 | 421 | int tcsetattr(int fd, int action, const struct termios *result) { 422 | if (action < 0 || action > 2) { 423 | errno = EINVAL; 424 | return -1; 425 | } 426 | 427 | return ioctl(fd, TCSETS + action, result); 428 | } 429 | 430 | int tcflow(int fd, int action) { 431 | return ioctl(fd, TCXONC, action); 432 | } 433 | 434 | int fchmod(int fd, mode_t mode) { 435 | int ret; 436 | LINUX_SYSCALL2(ret, 91, fd, mode); 437 | 438 | if (ret < 0) { 439 | errno = -ret; 440 | return -1; 441 | } 442 | 443 | return 0; 444 | } 445 | 446 | clock_t times(struct tms *t) { 447 | int ret; 448 | LINUX_SYSCALL1(ret, 100, t); 449 | 450 | if (ret < 0) { 451 | errno = -ret; 452 | return (clock_t)-1; 453 | } 454 | 455 | return ret; 456 | } 457 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/crt0.S: -------------------------------------------------------------------------------- 1 | .section .text 2 | .globl _start 3 | _start: 4 | xor %ebp, %ebp // Mark the end of stack frames 5 | mov (%rsp), %edi // Get argc from the stack 6 | lea 8(%rsp), %rsi // Take the address of argv from the stack 7 | lea 16(%rsp,%rdi,8), %rdx // Take the address of envp from the stack 8 | xor %eax, %eax // Per ABI and compatibility with icc 9 | call __slibc_init // Hand it off to the libc. 10 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/siglist.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int sys_nsig = 32; 4 | 5 | const char *const sys_siglist[] = { 6 | [SIGHUP] = "Hangup", 7 | [SIGINT] = "Terminal interrupt signal", 8 | [SIGQUIT] = "Terminal quit signal", 9 | [SIGILL] = "Illegal instruction", 10 | [SIGTRAP] = "Trace/breakpoint trap", 11 | [SIGABRT] = "Process abort signal", 12 | [SIGBUS] = "Access to an undefined portion of a memory object", 13 | [SIGFPE] = "Erroneous arithmetic operation", 14 | [SIGKILL] = "Kill (cannot be caught or ignored)", 15 | [SIGUSR1] = "User-defined signal 1", 16 | [SIGSEGV] = "Invalid memory reference", 17 | [SIGUSR2] = "User-defined signal 2", 18 | [SIGPIPE] = "Write on a pipe with no one to read it", 19 | [SIGTERM] = "Termination signal", 20 | [SIGSTKFLT] = "Stack fault", 21 | [SIGCHLD] = "Child process terminated, stopped", 22 | [SIGCONT] = "Continue executing, if stopped", 23 | [SIGSTOP] = "Stop executing (cannot be caught or ignored)", 24 | [SIGTSTP] = "Terminal stop signal", 25 | [SIGTTIN] = "Background process attempting read", 26 | [SIGTTOU] = "Background process attempting write", 27 | [SIGURG] = "High bandwidth data is available at a socket", 28 | [SIGXCPU] = "CPU time limit exceeded", 29 | [SIGXFSZ] = "File size limit exceeded", 30 | [SIGVTALRM] = "Virtual timer expired", 31 | [SIGPROF] = "Profiling timer expired", 32 | [SIGWINCH] = "Window size change", 33 | [SIGPOLL] = "Pollable event", 34 | [SIGPWR] = "Power failure restart", 35 | [SIGSYS] = "Bad system call", 36 | [SIGRTMIN] = "Real time signal min range", 37 | [SIGRTMAX] = "Real time signal max range" 38 | }; 39 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/errnoval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__ERRNOVAL_H__ 2 | #define __SYS__ERRNOVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define EDOM 1 9 | #define EILSEQ 2 10 | #define ERANGE 3 11 | #define E2BIG 1001 12 | #define EACCES 1002 13 | #define EADDRINUSE 1003 14 | #define EADDRNOTAVAIL 1004 15 | #define EAFNOSUPPORT 1005 16 | #define EAGAIN 1006 17 | #define EALREADY 1007 18 | #define EBADF 1008 19 | #define EBADMSG 1009 20 | #define EBUSY 1010 21 | #define ECANCELED 1011 22 | #define ECHILD 1012 23 | #define ECONNABORTED 1013 24 | #define ECONNREFUSED 1014 25 | #define ECONNRESET 1015 26 | #define EDEADLK 1016 27 | #define EDESTADDRREQ 1017 28 | #define EDQUOT 1018 29 | #define EEXIST 1019 30 | #define EFAULT 1020 31 | #define EFBIG 1021 32 | #define EHOSTUNREACH 1022 33 | #define EIDRM 1023 34 | #define EINPROGRESS 1024 35 | #define EINTR 1025 36 | #define EINVAL 1026 37 | #define EIO 1027 38 | #define EISCONN 1028 39 | #define EISDIR 1029 40 | #define ELOOP 1030 41 | #define EMFILE 1031 42 | #define EMLINK 1032 43 | #define EMSGSIZE 1034 44 | #define EMULTIHOP 1035 45 | #define ENAMETOOLONG 1036 46 | #define ENETDOWN 1037 47 | #define ENETRESET 1038 48 | #define ENETUNREACH 1039 49 | #define ENFILE 1040 50 | #define ENOBUFS 1041 51 | #define ENODEV 1042 52 | #define ENOENT 1043 53 | #define ENOEXEC 1044 54 | #define ENOLCK 1045 55 | #define ENOLINK 1046 56 | #define ENOMEM 1047 57 | #define ENOMSG 1048 58 | #define ENOPROTOOPT 1049 59 | #define ENOSPC 1050 60 | #define ENOSYS 1051 61 | #define ENOTCONN 1052 62 | #define ENOTDIR 1053 63 | #define ENOTEMPTY 1054 64 | #define ENOTRECOVERABLE 1055 65 | #define ENOTSOCK 1056 66 | #define ENOTSUP 1057 67 | #define ENOTTY 1058 68 | #define ENXIO 1059 69 | #define EOPNOTSUPP 1060 70 | #define EOVERFLOW 1061 71 | #define EOWNERDEAD 1062 72 | #define EPERM 1063 73 | #define EPIPE 1064 74 | #define EPROTO 1065 75 | #define EPROTONOSUPPORT 1066 76 | #define EPROTOTYPE 1067 77 | #define EROFS 1068 78 | #define ESPIPE 1069 79 | #define ESRCH 1070 80 | #define ESTALE 1071 81 | #define ETIMEDOUT 1072 82 | #define ETXTBSY 1073 83 | #define EWOULDBLOCK EAGAIN 84 | #define EXDEV 1075 85 | #define ENODATA 1076 86 | #define ETIME 1077 87 | #define ENOKEY 1078 88 | #define ESHUTDOWN 1079 89 | #define EHOSTDOWN 1080 90 | #define EBADFD 1081 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/fcntlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__FCNTLVAL_H__ 2 | #define __SYS__FCNTLVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // reserve 3 bits for the access mode 9 | #define O_ACCMODE 0x0007 10 | #define O_EXEC 1 11 | #define O_RDONLY 2 12 | #define O_RDWR 3 13 | #define O_SEARCH 4 14 | #define O_WRONLY 5 15 | // all remaining flags get their own bit 16 | #define O_APPEND 0x0008 17 | #define O_CREAT 0x0010 18 | #define O_DIRECTORY 0x0020 19 | #define O_EXCL 0x0040 20 | #define O_NOCTTY 0x0080 21 | #define O_NOFOLLOW 0x0100 22 | #define O_TRUNC 0x0200 23 | #define O_NONBLOCK 0x0400 24 | #define O_DSYNC 0x0800 25 | #define O_RSYNC 0x1000 26 | #define O_SYNC 0x2000 27 | #define O_CLOEXEC 0x4000 28 | 29 | // constants for fcntl()'s command argument 30 | #define F_DUPFD 1 31 | #define F_DUPFD_CLOEXEC 2 32 | #define F_GETFD 3 33 | #define F_SETFD 4 34 | #define F_GETFL 5 35 | #define F_SETFL 6 36 | #define F_GETLK 7 37 | #define F_SETLK 8 38 | #define F_SETLKW 9 39 | #define F_GETOWN 10 40 | #define F_SETOWN 11 41 | 42 | // constants for struct flock's l_type member 43 | #define F_RDLCK 1 44 | #define F_UNLCK 2 45 | #define F_WRLCK 3 46 | 47 | // constants for fcntl()'s additional argument of F_GETFD and F_SETFD 48 | #define FD_CLOEXEC 1 49 | 50 | #define F_GETPATH 100 51 | 52 | #define SEEK_CUR 1 53 | #define SEEK_END 2 54 | #define SEEK_SET 3 55 | 56 | #define F_OK 1 57 | #define R_OK 2 58 | #define W_OK 4 59 | #define X_OK 8 60 | 61 | struct flock { 62 | short l_type; 63 | short l_whence; 64 | off_t l_start; 65 | off_t l_len; 66 | pid_t l_pid; 67 | }; 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/ioctlval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__IOCTLVAL_H__ 2 | #define __SYS__IOCTLVAL_H__ 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/signalval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__SIGNALVAL_H__ 2 | #define __SYS__SIGNALVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define SIG_ERR ((__sighandler)(void *)(-1)) 9 | #define SIG_DFL ((__sighandler)(void *)(-2)) 10 | #define SIG_IGN ((__sighandler)(void *)(-3)) 11 | 12 | #define SIGHUP 1 13 | #define SIGINT 2 14 | #define SIGQUIT 3 15 | #define SIGILL 4 16 | #define SIGTRAP 5 17 | #define SIGABRT 6 18 | #define SIGBUS 7 19 | #define SIGFPE 8 20 | #define SIGKILL 9 21 | #define SIGUSR1 10 22 | #define SIGSEGV 11 23 | #define SIGUSR2 12 24 | #define SIGPIPE 13 25 | #define SIGALRM 14 26 | #define SIGTERM 15 27 | #define SIGSTKFLT 16 28 | #define SIGCHLD 17 29 | #define SIGCONT 18 30 | #define SIGSTOP 19 31 | #define SIGTSTP 20 32 | #define SIGTTIN 21 33 | #define SIGTTOU 22 34 | #define SIGURG 23 35 | #define SIGXCPU 24 36 | #define SIGXFSZ 25 37 | #define SIGVTALRM 26 38 | #define SIGPROF 27 39 | #define SIGWINCH 28 40 | #define SIGIO 29 41 | #define SIGPOLL SIGIO 42 | #define SIGPWR 30 43 | #define SIGSYS 31 44 | #define SIGRTMIN 32 45 | #define SIGRTMAX 33 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/statval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__STATVAL_H__ 2 | #define __SYS__STATVAL_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define S_IFMT 0x0F000 12 | #define S_IFBLK 0x06000 13 | #define S_IFCHR 0x02000 14 | #define S_IFIFO 0x01000 15 | #define S_IFREG 0x08000 16 | #define S_IFDIR 0x04000 17 | #define S_IFLNK 0x0A000 18 | #define S_IFSOCK 0x0C000 19 | #define S_IRWXU 0700 20 | #define S_IRUSR 0400 21 | #define S_IWUSR 0200 22 | #define S_IXUSR 0100 23 | #define S_IRWXG 070 24 | #define S_IRGRP 040 25 | #define S_IWGRP 020 26 | #define S_IXGRP 010 27 | #define S_IRWXO 07 28 | #define S_IROTH 04 29 | #define S_IWOTH 02 30 | #define S_IXOTH 01 31 | #define S_ISUID 04000 32 | #define S_ISGID 02000 33 | #define S_ISVTX 01000 34 | #define S_IREAD S_IRUSR 35 | #define S_IWRITE S_IWUSR 36 | #define S_IEXEC S_IXUSR 37 | 38 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 39 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 40 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 41 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 42 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 43 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 44 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 45 | 46 | #define st_atime st_atim.tv_sec 47 | #define st_mtime st_mtim.tv_sec 48 | #define st_ctime st_ctim.tv_sec 49 | 50 | struct stat { 51 | dev_t st_dev; 52 | ino_t st_ino; 53 | mode_t st_mode; 54 | nlink_t st_nlink; 55 | uid_t st_uid; 56 | gid_t st_gid; 57 | dev_t st_rdev; 58 | off_t st_size; 59 | struct timespec st_atim; 60 | struct timespec st_mtim; 61 | struct timespec st_ctim; 62 | blksize_t st_blksize; 63 | blkcnt_t st_blocks; 64 | }; 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/termiosval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TERMIOSVAL_H__ 2 | #define __SYS__TERMIOSVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef unsigned int cc_t; 9 | typedef unsigned int speed_t; 10 | typedef unsigned int tcflag_t; 11 | 12 | #define NCCS 11 13 | #define VEOF 0 14 | #define VEOL 1 15 | #define VERASE 2 16 | #define VINTR 3 17 | #define VKILL 4 18 | #define VMIN 5 19 | #define VQUIT 6 20 | #define VSTART 7 21 | #define VSTOP 8 22 | #define VSUSP 9 23 | #define VTIME 10 24 | 25 | struct termios { 26 | tcflag_t c_iflag; 27 | tcflag_t c_oflag; 28 | tcflag_t c_cflag; 29 | tcflag_t c_lflag; 30 | cc_t c_cc[NCCS]; 31 | speed_t ibaud; 32 | speed_t obaud; 33 | }; 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/timesval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMESVAL_H__ 2 | #define __SYS__TIMESVAL_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct tms { 9 | clock_t tms_utime; 10 | clock_t tms_stime; 11 | clock_t tms_cutime; 12 | clock_t tms_cstime; 13 | }; 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/timeval.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TIMEVAL_H__ 2 | #define __SYS__TIMEVAL_H__ 3 | 4 | #include 5 | 6 | #define CLOCK_REALTIME 0 7 | #define CLOCK_MONOTONIC 1 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | struct timespec { 14 | time_t tv_sec; 15 | long tv_nsec; 16 | }; 17 | 18 | struct timeval { 19 | time_t tv_sec; 20 | suseconds_t tv_usec; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sys/types.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYS__TYPES_H__ 2 | #define __SYS__TYPES_H__ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef uint64_t dev_t; 11 | typedef uint64_t ino_t; 12 | typedef int32_t mode_t; 13 | typedef uint64_t nlink_t; 14 | typedef int32_t uid_t; 15 | typedef int32_t gid_t; 16 | typedef int64_t time_t; 17 | typedef int64_t suseconds_t; 18 | typedef int64_t blksize_t; 19 | typedef int64_t blkcnt_t; 20 | typedef int32_t pid_t; 21 | typedef int64_t off_t; 22 | typedef int64_t ssize_t; 23 | typedef int64_t clockid_t; 24 | typedef int64_t clock_t; 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /source/ports/x86_64-qword/sysdeps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int fcntl(int fd, int command, ...) { 14 | va_list args; 15 | va_start(args, command); 16 | int ret; 17 | int sys_errno; 18 | size_t arg = va_arg(args, size_t); 19 | 20 | asm volatile ( 21 | "syscall" 22 | : "=a"(ret), "=d"(sys_errno) 23 | : "a"(18), "D"(fd), "S"(command), "d"(arg) 24 | : "rcx", "r11" 25 | ); 26 | 27 | if (ret == -1) { 28 | errno = sys_errno; 29 | } 30 | 31 | return ret; 32 | } 33 | 34 | int open(const char *path, int oflag, ...) { 35 | int ret; 36 | int sys_errno; 37 | 38 | asm volatile ( 39 | "syscall" 40 | : "=a"(ret), "=d"(sys_errno) 41 | : "a"(1), "D"(path), "S"(oflag), "d"(0) 42 | : "rcx", "r11" 43 | ); 44 | 45 | if (ret == -1) { 46 | errno = sys_errno; 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | int close(int fd) { 53 | int ret; 54 | int sys_errno; 55 | 56 | asm volatile ( 57 | "syscall" 58 | : "=a"(ret), "=d"(sys_errno) 59 | : "a"(2), "D"(fd) 60 | : "rcx", "r11" 61 | ); 62 | 63 | if (ret == -1) { 64 | errno = sys_errno; 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | ssize_t read(int fd, void *buf, size_t count) { 71 | ssize_t ret; 72 | int sys_errno; 73 | 74 | asm volatile ( 75 | "syscall" 76 | : "=a"(ret), "=d"(sys_errno) 77 | : "a"(3), "D"(fd), "S"(buf), "d"(count) 78 | : "rcx", "r11" 79 | ); 80 | 81 | if (ret == -1) { 82 | errno = sys_errno; 83 | } 84 | 85 | return ret; 86 | } 87 | 88 | ssize_t write(int fd, const void *buf, size_t count) { 89 | ssize_t ret; 90 | int sys_errno; 91 | 92 | asm volatile ( 93 | "syscall" 94 | : "=a"(ret), "=d"(sys_errno) 95 | : "a"(3), "D"(fd), "S"(buf), "d"(count) 96 | : "rcx", "r11"); 97 | 98 | if (ret == -1) { 99 | errno = sys_errno; 100 | } 101 | 102 | return ret; 103 | } 104 | 105 | char *getcwd(char *buf, size_t size) { 106 | int ret; 107 | int sys_errno; 108 | 109 | asm volatile ( 110 | "syscall" 111 | : "=a"(ret), "=d"(sys_errno) 112 | : "a"(20), "D"(buf), "S"(size) 113 | : "rcx", "r11" 114 | ); 115 | 116 | if (ret == -1) { 117 | errno = sys_errno; 118 | } 119 | 120 | return 0; 121 | } 122 | 123 | int rmdir(const char *path) { 124 | // TODO: Qword does not really support this. 125 | (void)path; 126 | return -1; 127 | } 128 | 129 | int unlink(const char *path) { 130 | int ret; 131 | int sys_errno; 132 | 133 | asm volatile ( 134 | "syscall" 135 | : "=a"(ret), "=d"(sys_errno) 136 | : "a"(34), "D"(path) 137 | : "rcx", "r11" 138 | ); 139 | 140 | if (ret == -1) { 141 | errno = sys_errno; 142 | } 143 | 144 | return 0; 145 | } 146 | 147 | int fork(void) { 148 | pid_t ret; 149 | int sys_errno; 150 | 151 | asm volatile ( 152 | "syscall" 153 | : "=a"(ret), "=d"(sys_errno) 154 | : "a"(10) 155 | : "rcx", "r11" 156 | ); 157 | 158 | if (ret == -1) { 159 | errno = sys_errno; 160 | } 161 | 162 | return ret; 163 | } 164 | 165 | void _exit(int error_code) { 166 | asm volatile ("syscall" :: "a"(12), "D"(error_code) : "rcx", "r11", "rdx"); 167 | } 168 | 169 | off_t lseek(int fd, off_t offset, int whence) { 170 | off_t ret; 171 | int sys_errno; 172 | 173 | asm volatile ( 174 | "syscall" 175 | : "=a"(ret), "=d"(sys_errno) 176 | : "a"(8), "D"(fd), "S"(offset), "d"(whence) 177 | : "rcx", "r11" 178 | ); 179 | 180 | if (ret == -1) { 181 | errno = sys_errno; 182 | } 183 | 184 | return ret; 185 | } 186 | 187 | #define PAGE_SIZE 0x1000 188 | 189 | static void* __sbrk_base = NULL; 190 | static size_t __sbrk_pages = 0; 191 | static size_t __sbrk_size = 0; 192 | 193 | void *sbrk(intptr_t increment) { 194 | ssize_t size_left = (__sbrk_pages * PAGE_SIZE) - __sbrk_size; 195 | 196 | if (increment > size_left) { 197 | size_t size_needed = increment - size_left; 198 | size_t pages_needed = (size_needed + (PAGE_SIZE - 1)) / PAGE_SIZE; 199 | 200 | void *ret; 201 | int sys_errno; 202 | asm volatile ( 203 | "syscall" 204 | : "=a"(ret), "=d"(sys_errno) 205 | : "a"(6), "D"(0), "S"(pages_needed) 206 | : "rcx", "r11" 207 | ); 208 | 209 | if (ret == NULL) { 210 | errno = sys_errno; 211 | return (void *)-1; 212 | } 213 | 214 | __sbrk_pages += pages_needed; 215 | __sbrk_size += increment; 216 | if (__sbrk_base == NULL) { 217 | __sbrk_base = ret; 218 | } 219 | } else if (increment < 0) { 220 | __sbrk_size -= increment; 221 | } 222 | 223 | return (void *)((size_t)__sbrk_base + __sbrk_size); 224 | } 225 | 226 | int stat(const char *path, struct stat *result) { 227 | int fd = open(path, O_RDONLY); 228 | if (fd == -1) { 229 | return -1; 230 | } 231 | 232 | int ret; 233 | int sys_errno; 234 | 235 | asm volatile ( 236 | "syscall" 237 | : "=a"(ret), "=d"(sys_errno) 238 | : "a"(9), "D"(fd), "S"(result) 239 | : "rcx", "r11" 240 | ); 241 | 242 | if (ret == -1) { 243 | errno = sys_errno; 244 | } 245 | 246 | close(fd); 247 | return ret; 248 | } 249 | 250 | int fstat(int fd, struct stat *result) { 251 | int ret; 252 | int sys_errno; 253 | 254 | asm volatile ( 255 | "syscall" 256 | : "=a"(ret), "=d"(sys_errno) 257 | : "a"(9), "D"(fd), "S"(result) 258 | : "rcx", "r11" 259 | ); 260 | 261 | if (ret == -1) { 262 | errno = sys_errno; 263 | return -1; 264 | } 265 | 266 | return 0; 267 | } 268 | 269 | int clock_gettime(clockid_t clock_id, struct timespec *tp) { 270 | int ret; 271 | int sys_errno; 272 | 273 | asm volatile( 274 | "syscall" 275 | : "=a"(ret), "=d"(sys_errno) 276 | : "a"(25), "D"(clock_id), "S"(tp) 277 | : "rcx", "r11" 278 | ); 279 | 280 | if (ret == -1) { 281 | errno = sys_errno; 282 | } 283 | 284 | return 0; 285 | } 286 | 287 | int sched_yield(void) { 288 | // TODO: Implement this once qword has it, if ever. 289 | return -1; 290 | } 291 | 292 | int access(const char *path, int amode) { 293 | (void)amode; 294 | 295 | int fd = open(path, O_RDWR); 296 | if (fd == -1) { 297 | return -1; 298 | } 299 | 300 | close(fd); 301 | return 0; 302 | } 303 | 304 | 305 | int pipe(int fds[2]) { 306 | int ret; 307 | int sys_errno; 308 | 309 | asm volatile ( 310 | "syscall" 311 | : "=a"(ret), "=d"(sys_errno) 312 | : "a"(19), "D"(fds), "S"(0) 313 | : "rcx", "r11" 314 | ); 315 | 316 | if (ret == -1) { 317 | errno = sys_errno; 318 | return -1; 319 | } 320 | 321 | return 0; 322 | } 323 | 324 | pid_t getpid(void) { 325 | pid_t pid; 326 | asm volatile ( 327 | "syscall" 328 | : "=a"(pid) 329 | : "a"(5) 330 | : "rcx", "r11", "rdx" 331 | ); 332 | return pid; 333 | } 334 | 335 | pid_t getppid(void) { 336 | pid_t ppid; 337 | asm volatile ( 338 | "syscall" 339 | : "=a"(ppid) 340 | : "a"(14) 341 | : "rcx", "r11", "rdx" 342 | ); 343 | return ppid; 344 | } 345 | 346 | pid_t getpgrp(void) { 347 | pid_t pgid; 348 | asm volatile ( 349 | "syscall" 350 | : "=a"(pgid) 351 | : "a"(38), "D"(0) 352 | : "rcx", "r11", "rdx" 353 | ); 354 | return pgid; 355 | } 356 | 357 | gid_t getgid(void) { 358 | // TODO: Implement when qword supports it. 359 | assert(!"This is a stub"); 360 | return 0; 361 | } 362 | 363 | int setgid(gid_t gid) { 364 | // TODO: Implement when qword supports it. 365 | (void)gid; 366 | assert(!"This is a stub"); 367 | return -1; 368 | } 369 | 370 | gid_t getegid(void) { 371 | // TODO: Implement when qword supports it. 372 | assert(!"This is a stub"); 373 | return 0; 374 | } 375 | 376 | uid_t getuid(void) { 377 | // TODO: Implement when qword supports it. 378 | assert(!"This is a stub"); 379 | return 0; 380 | } 381 | 382 | int setuid(uid_t uid) { 383 | int ret; 384 | asm volatile ( 385 | "syscall" 386 | : "=a" (ret) 387 | : "a"(39), "D"(uid) 388 | : "rcx", "r11", "rdx" 389 | ); 390 | return ret; 391 | } 392 | 393 | uid_t geteuid(void) { 394 | // TODO: Implement when qword supports it. 395 | assert(!"This is a stub"); 396 | return 0; 397 | } 398 | 399 | int execve(const char *path, char *const argv[], char *const envp[]) { 400 | int ret; 401 | int sys_errno; 402 | 403 | asm volatile ( 404 | "syscall" 405 | : "=a"(ret), "=d"(sys_errno) 406 | : "a"(11), "D"(path), "S"(argv), "d"(envp) 407 | : "rcx", "r11" 408 | ); 409 | 410 | if (ret == -1) { 411 | errno = sys_errno; 412 | } 413 | 414 | return ret; 415 | } 416 | 417 | int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { 418 | asm volatile ( 419 | "syscall" 420 | : 421 | : "a"(40), "D"(rqtp->tv_sec + (rqtp->tv_nsec / 1000000000)) 422 | : "rcx", "r11" 423 | ); 424 | 425 | if (rmtp != NULL) { 426 | rmtp->tv_sec = 0; 427 | rmtp->tv_nsec = 0; 428 | } 429 | 430 | return 0; 431 | } 432 | 433 | int ttyname_r(int fd, char *name, size_t namesize) { 434 | // TODO: Implement when qword supports it. 435 | (void)fd; 436 | (void)name; 437 | (void)namesize; 438 | assert(!"This is a stub"); 439 | return -1; 440 | } 441 | 442 | unsigned alarm(unsigned seconds) { 443 | // TODO: Implement when echidnaOS supports it. 444 | (void)seconds; 445 | assert(!"This is a stub"); 446 | return 0; 447 | } 448 | 449 | int kill(pid_t pid, int signal) { 450 | int ret; 451 | int sys_errno; 452 | 453 | asm volatile ( 454 | "syscall" 455 | : "=a"(ret), "=d"(sys_errno) 456 | : "a"(27), "D"(pid), "S"(signal) 457 | : "rcx", "r11" 458 | ); 459 | 460 | if (ret == -1) { 461 | errno = sys_errno; 462 | return -1; 463 | } 464 | 465 | return 0; 466 | } 467 | 468 | int ioctl(int fd, int request, ...) { 469 | // TODO: Implement when qwordOS supports it. 470 | (void)fd; 471 | (void)request; 472 | assert(!"This is a stub"); 473 | return -1; 474 | } 475 | 476 | int tcgetattr(int fd, struct termios *result) { 477 | int ret; 478 | int sys_errno; 479 | 480 | asm volatile ( 481 | "syscall" 482 | : "=a"(ret), "=d"(sys_errno) 483 | : "a"(24), "D"(fd), "S"(result) 484 | : "rcx", "r11" 485 | ); 486 | 487 | if (ret == -1) { 488 | errno = sys_errno; 489 | return -1; 490 | } 491 | 492 | return 0; 493 | } 494 | 495 | int tcsetattr(int fd, int action, const struct termios *result) { 496 | int ret; 497 | int sys_errno; 498 | asm volatile ( 499 | "syscall" 500 | : "=a"(ret), "=d"(sys_errno) 501 | : "a"(23), "D"(fd), "S"(action), "d"(result) 502 | : "rcx", "r11" 503 | ); 504 | 505 | if (ret == -1) { 506 | errno = sys_errno; 507 | return -1; 508 | } 509 | 510 | return 0; 511 | } 512 | 513 | int tcflow(int fd, int action) { 514 | int ret; 515 | int sys_errno; 516 | asm volatile ( 517 | "syscall" 518 | : "=a"(ret), "=d"(sys_errno) 519 | : "a"(30), "D"(fd), "S"(action) 520 | : "rcx", "r11" 521 | ); 522 | 523 | if (ret == -1) { 524 | errno = sys_errno; 525 | return -1; 526 | } 527 | 528 | return 0; 529 | } 530 | 531 | int fchmod(int fd, mode_t mode) { 532 | // TODO: Implement when qword supports it. 533 | (void)fd; 534 | (void)mode; 535 | assert(!"This is a stub"); 536 | return -1; 537 | } 538 | 539 | clock_t times(struct tms *t) { 540 | // TODO: Implement when echidnaOS supports it. 541 | (void)t; 542 | assert(!"This is a stub"); 543 | return (clock_t)-1; 544 | } 545 | -------------------------------------------------------------------------------- /test/libc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define CWD_LEN 300 10 | 11 | static jmp_buf buffer; 12 | 13 | int main(int argc, char *argv[]) { 14 | char cwd[CWD_LEN]; 15 | int ret = setjmp(buffer); 16 | printf("Running from: %s\n", getcwd(cwd, CWD_LEN)); 17 | for (int i = 0; i < argc; i++) { 18 | puts(argv[i]); 19 | } 20 | 21 | void *ptr1 = malloc(30); 22 | printf("%p\n", ptr1); 23 | void *ptr2 = malloc(0x1000000); 24 | printf("%p\n", ptr2); 25 | free(ptr1); 26 | ptr1 = malloc(30); 27 | printf("%p\n", ptr1); 28 | ptr2 = realloc(ptr2, 22); 29 | printf("%p\n", ptr2); 30 | free(ptr1); 31 | free(ptr2); 32 | 33 | printf("The value of SHELL is: %s\n", getenv("SHELL")); 34 | printf("The time is: %lu \n", time(NULL)); 35 | 36 | if (ret == 0) longjmp(buffer, 0); 37 | 38 | pid_t f = fork(); 39 | if (f == 0) { 40 | char *argv[] = {"ls", NULL}; 41 | execvpe(argv[0], argv, environ); 42 | } else { 43 | sleep(3); 44 | printf("Killing our child %i\n", f); 45 | kill(f, SIGKILL); 46 | } 47 | 48 | puts(strstr("https://test.com", "ttps:")); 49 | return 0; 50 | } 51 | --------------------------------------------------------------------------------