commit b686116502e7777bc0b64e1c9c3e0fe9caa03837 Author: Gitea Date: Sun Jan 31 14:08:26 2021 -0600 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ffc911 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +isodir +kernel +libc +interface_manual +man_pages +old_stuff +static_system_stuff +sysroot +utils +*.iso +*~ +#*# +.vscode +dev_tools/build_util_src/*.tar.xz +dev_tools/build_util_src/higher_half_test +notes/FreeBSD's bootloader.png +notes/quick_sort_explore.c \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..60569f2 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e +. ./headers.sh + +for PROJECT in $PROJECTS; do + (cd $PROJECT && DESTDIR="$SYSROOT" $MAKE install) +done diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000..9044941 --- /dev/null +++ b/clean.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e +. ./config.sh + +for PROJECT in $PROJECTS; do + (cd $PROJECT && $MAKE clean) +done + +rm -rf sysroot +rm -rf isodir +rm -rf fenix.iso diff --git a/config.sh b/config.sh new file mode 100755 index 0000000..1dd77b1 --- /dev/null +++ b/config.sh @@ -0,0 +1,27 @@ +SYSTEM_HEADER_PROJECTS="libc kernel" +PROJECTS="libc kernel" + +export MAKE=${MAKE:-make} +export HOST=${HOST:-$(./default-host.sh)} + +export AR=${HOST}-ar +export AS=${HOST}-as +export CC=${HOST}-gcc + +export PREFIX=/usr +export EXEC_PREFIX=$PREFIX +export BOOTDIR=/boot +export LIBDIR=$EXEC_PREFIX/lib +export INCLUDEDIR=$PREFIX/include + +export CFLAGS='-O2 -g' +export CPPFLAGS='' + +# Sysroot time! +export SYSROOT="$(pwd)/sysroot" +export CC="$CC --sysroot=$SYSROOT" + +# A workaround for -elf gcc targets +if echo "$HOST" | grep -Eq -- '-elf($|-)'; then + export CC="$CC -isystem=$INCLUDEDIR" +fi diff --git a/default-host.sh b/default-host.sh new file mode 100755 index 0000000..471c3d2 --- /dev/null +++ b/default-host.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo i686-elf diff --git a/dev_tools/build_util_src/README b/dev_tools/build_util_src/README new file mode 100644 index 0000000..f32ee0c --- /dev/null +++ b/dev_tools/build_util_src/README @@ -0,0 +1,41 @@ +This script automatically builds the cross-compiler needed to build FENIX at +this stage in time. It sets up a cross-compiler for i686-elf in ~/opt/cross. + +This version of the script, suitable for building current, unversioned +pre-releases of FENIX, uses GCC 9.2.0 and Binutils 2.32. You'll need to +download these from the GNU website: + Binutils: https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.xz + GCC: https://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.xz +Download these tarballs into the same folder as build_cross_compiler.sh + +Additionally, you'll need the following: + - A suitable C compiler (probably GCC) + - make + - Bison + - Flex + - GMP + - MPC + - MPFR + - Texinfo + +These correspond to these Fedora packages: + - gcc (or whatever C compiler you use, like Clang) + - make + - bison + - flex + - gmp-devel + - libmpc-devel + - mpfr-devel + - texinfo + +Once you're ready, simply run build_cross_compiler.sh. (You may first need +to run `chmod +x build_cross_compiler.sh` in order to make it executable. + +Once done, you'll probably want to add ~/opt/cross/bin to your PATH. You'll +probably also want to verify that it worked. To do so, you can start by +checking if it runs using: + `i686-elf-gcc --version` +You can also try compiling a small test kernel included in cross_compiler_test. +Simply run `make`. If everything worked, it should successfully compile. You can +then run `make test` to open the kernel in QEMU. (Note: You'll need +qemu-system-i386 to test the test kernel. \ No newline at end of file diff --git a/dev_tools/build_util_src/build_cross_compiler.sh b/dev_tools/build_util_src/build_cross_compiler.sh new file mode 100755 index 0000000..c7892ff --- /dev/null +++ b/dev_tools/build_util_src/build_cross_compiler.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Extract binutils and gcc +# You can try changing versions, if you want. +# The official setup is binutils 2.32 and GCC 9.2.0 +tar -xvf binutils-2.32.tar.xz +tar -xvf gcc-9.2.0.tar.xz + +# We'll eventuall change to, like, i686-fenix or something, +# but, for now, this is what we'll use. +# Besides, we'd need patches for a custom OS target +TARGET=i686-elf +PREFIX="$HOME/opt-test/cross" +PATH="$PREFIX/bin:$PATH" + +# Go ahead and make sure the prefix exists +mkdir -p $PREFIX + +# Binutils build +mkdir build-binutils +cd build-binutils +# Binutils w/o native language support. Feel free to remove --disable-nls +# if you want stuff in your native language. Also, enable sysroot support. +../binutils-2.32/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror +make +make install + +# GCC build +cd .. +mkdir build-gcc +cd build-gcc +# Check for $PREFIX/bin in PATH +which -- $TARGET-as || exit 1 +# GCC w/o NLS and with only C support. Also, it shouldn't rely on having +# headers available to it. You can optionally remove --disable-nls for +# nativle language stuffs, or add ,C++ to languages, if you wanna have C++. +../gcc-9.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c --without-headers +make all-gcc +make all-target-libgcc +make install-gcc +make install-target-libgcc diff --git a/dev_tools/build_util_src/cross_compiler_test/Makefile b/dev_tools/build_util_src/cross_compiler_test/Makefile new file mode 100644 index 0000000..d9886fe --- /dev/null +++ b/dev_tools/build_util_src/cross_compiler_test/Makefile @@ -0,0 +1,24 @@ +# Reminder that you'll need the cross compiler toolchain setup already. +PREFIX = i686-elf- +CC = $(PREFIX)gcc +AS = $(PREFIX)as +CFLAGS = -ffreestanding -O2 +WARNFLAGS = -Wall -Wextra + +all: test.bin + +test: test.bin + grub-file --is-x86-multiboot test.bin + qemu-system-i386 -kernel test.bin + +test.bin: boot.o kernel.o linker.ld + $(CC) -T linker.ld -o test.bin $(CFLAGS) -nostdlib boot.o kernel.o -lgcc + +boot.o: boot.s + $(AS) boot.s -o boot.o + +kernel.o: kernel.c + $(CC) -c kernel.c -o kernel.o -std=gnu99 $(CFLAGS) $(WARNFLAGS) + +clean: + -rm *.o test.bin diff --git a/dev_tools/build_util_src/cross_compiler_test/boot.s b/dev_tools/build_util_src/cross_compiler_test/boot.s new file mode 100755 index 0000000..33072fe --- /dev/null +++ b/dev_tools/build_util_src/cross_compiler_test/boot.s @@ -0,0 +1,109 @@ +/* Declare constants for the multiboot header. */ +.set ALIGN, 1<<0 /* align loaded modules on page boundaries */ +.set MEMINFO, 1<<1 /* provide memory map */ +.set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */ +.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ +.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ + +/* +Declare a multiboot header that marks the program as a kernel. These are magic +values that are documented in the multiboot standard. The bootloader will +search for this signature in the first 8 KiB of the kernel file, aligned at a +32-bit boundary. The signature is in its own section so the header can be +forced to be within the first 8 KiB of the kernel file. +*/ +.section .multiboot +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + +/* +The multiboot standard does not define the value of the stack pointer register +(esp) and it is up to the kernel to provide a stack. This allocates room for a +small stack by creating a symbol at the bottom of it, then allocating 16384 +bytes for it, and finally creating a symbol at the top. The stack grows +downwards on x86. The stack is in its own section so it can be marked nobits, +which means the kernel file is smaller because it does not contain an +uninitialized stack. The stack on x86 must be 16-byte aligned according to the +System V ABI standard and de-facto extensions. The compiler will assume the +stack is properly aligned and failure to align the stack will result in +undefined behavior. +*/ +.section .bss +.align 16 +stack_bottom: +.skip 16384 # 16 KiB +stack_top: + +/* +The linker script specifies _start as the entry point to the kernel and the +bootloader will jump to this position once the kernel has been loaded. It +doesn't make sense to return from this function as the bootloader is gone. +*/ +.section .text +.global _start +.type _start, @function +_start: + /* + The bootloader has loaded us into 32-bit protected mode on a x86 + machine. Interrupts are disabled. Paging is disabled. The processor + state is as defined in the multiboot standard. The kernel has full + control of the CPU. The kernel can only make use of hardware features + and any code it provides as part of itself. There's no printf + function, unless the kernel provides its own header and a + printf implementation. There are no security restrictions, no + safeguards, no debugging mechanisms, only what the kernel provides + itself. It has absolute and complete power over the + machine. + */ + + /* + To set up a stack, we set the esp register to point to the top of the + stack (as it grows downwards on x86 systems). This is necessarily done + in assembly as languages such as C cannot function without a stack. + */ + mov $stack_top, %esp + + /* + This is a good place to initialize crucial processor state before the + high-level kernel is entered. It's best to minimize the early + environment where crucial features are offline. Note that the + processor is not fully initialized yet: Features such as floating + point instructions and instruction set extensions are not initialized + yet. The GDT should be loaded here. Paging should be enabled here. + C++ features such as global constructors and exceptions will require + runtime support to work as well. + */ + + /* + Enter the high-level kernel. The ABI requires the stack is 16-byte + aligned at the time of the call instruction (which afterwards pushes + the return pointer of size 4 bytes). The stack was originally 16-byte + aligned above and we've pushed a multiple of 16 bytes to the + stack since (pushed 0 bytes so far), so the alignment has thus been + preserved and the call is well defined. + */ + call kernel_main + + /* + If the system has nothing more to do, put the computer into an + infinite loop. To do that: + 1) Disable interrupts with cli (clear interrupt enable in eflags). + They are already disabled by the bootloader, so this is not needed. + Mind that you might later enable interrupts and return from + kernel_main (which is sort of nonsensical to do). + 2) Wait for the next interrupt to arrive with hlt (halt instruction). + Since they are disabled, this will lock up the computer. + 3) Jump to the hlt instruction if it ever wakes up due to a + non-maskable interrupt occurring or due to system management mode. + */ + cli +1: hlt + jmp 1b + +/* +Set the size of the _start symbol to the current location '.' minus its start. +This is useful when debugging or when you implement call tracing. +*/ +.size _start, . - _start diff --git a/dev_tools/build_util_src/cross_compiler_test/kernel.c b/dev_tools/build_util_src/cross_compiler_test/kernel.c new file mode 100755 index 0000000..86c7d07 --- /dev/null +++ b/dev_tools/build_util_src/cross_compiler_test/kernel.c @@ -0,0 +1,114 @@ +#include +#include +#include + +/* Check if the compiler thinks you are targeting the wrong operating system. */ +#if defined(__linux__) +#error "You are not using a cross-compiler, you will most certainly run into trouble" +#endif + +/* This tutorial will only work for the 32-bit ix86 targets. */ +#if !defined(__i386__) +#error "This tutorial needs to be compiled with a ix86-elf compiler" +#endif + +/* Hardware text mode color constants. */ +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) +{ + return fg | bg << 4; +} + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color) +{ + return (uint16_t) uc | (uint16_t) color << 8; +} + +size_t strlen(const char* str) +{ + size_t len = 0; + while (str[len]) + len++; + return len; +} + +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +size_t terminal_row; +size_t terminal_column; +uint8_t terminal_color; +uint16_t* terminal_buffer; + +void terminal_initialize(void) +{ + terminal_row = 0; + terminal_column = 0; + terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + terminal_buffer = (uint16_t*) 0xB8000; + for (size_t y = 0; y < VGA_HEIGHT; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(' ', terminal_color); + } + } +} + +void terminal_setcolor(uint8_t color) +{ + terminal_color = color; +} + +void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) +{ + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(c, color); +} + +void terminal_putchar(char c) +{ + terminal_putentryat(c, terminal_color, terminal_column, terminal_row); + if (++terminal_column == VGA_WIDTH) { + terminal_column = 0; + if (++terminal_row == VGA_HEIGHT) + terminal_row = 0; + } +} + +void terminal_write(const char* data, size_t size) +{ + for (size_t i = 0; i < size; i++) + terminal_putchar(data[i]); +} + +void terminal_writestring(const char* data) +{ + terminal_write(data, strlen(data)); +} + +void kernel_main(void) +{ + /* Initialize terminal interface */ + terminal_initialize(); + + /* Newline support is left as an exercise. */ + terminal_writestring("Hello, kernel World!\n"); +} diff --git a/dev_tools/build_util_src/cross_compiler_test/linker.ld b/dev_tools/build_util_src/cross_compiler_test/linker.ld new file mode 100755 index 0000000..38ddd94 --- /dev/null +++ b/dev_tools/build_util_src/cross_compiler_test/linker.ld @@ -0,0 +1,43 @@ +/* The bootloader will look at this image and start execution at the symbol + designated as the entry point. */ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + /* Begin putting sections at 1 MiB, a conventional place for kernels to be + loaded at by the bootloader. */ + . = 1M; + + /* First put the multiboot header, as it is required to be put very early + early in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + /* The compiler may produce other sections, by default it will put them in + a segment with the same name. Simply add stuff here as needed. */ +} diff --git a/headers.sh b/headers.sh new file mode 100755 index 0000000..5250d2d --- /dev/null +++ b/headers.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e +. ./config.sh + +mkdir -p "$SYSROOT" + +for PROJECT in $SYSTEM_HEADER_PROJECTS; do + (cd $PROJECT && DESTDIR="$SYSROOT" $MAKE install-headers) +done diff --git a/iso.sh b/iso.sh new file mode 100755 index 0000000..48991e2 --- /dev/null +++ b/iso.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e +. ./build.sh + +mkdir -p isodir +mkdir -p isodir/boot +mkdir -p isodir/boot/grub + +cp sysroot/boot/fenix.kernel isodir/boot/fenix.kernel +cat > isodir/boot/grub/grub.cfg </fxfsdefaults11 +UUID=[uuid]noneswapdefaults00 +----- +device is a name, label, or UUID for a block device +mount-point is the folder to mount it in (for swap, it's none) +fs-type is the filesystem type +options is the options for mounting +dump is how often it's backed up by dump (0 is never) +pass is the order for checking by fsck (0 don't, 1 immediately, 2 after boot) +----- +FS options +auto/noauto - automatically mount on boot or only explicitly +dev/nodev - behaviour of interpretation of block special devices +exec/noexec - can binaries be executed +rw/ro - read/write or read-only +sync/async - synchronous/asynchronous IO (are writes done when commands issued?) +suid/nosuid - operation of the suid and sgid bits +user/users/nouser - anyone can mount, group users can mount, root can mount + user implicitly implies noexec, nosuid, nodev +defaults - default set (i.e. rw, suid, dev, exec, auto, nouser, async) +check=[none, normal, strict] - fsck checking level (ext/probably fxfs) +check=[r, n, s] - policy for allowed filenames (vfat) + r - relaxed, n - normal, s - strict +windows_names - only allow windows characters in names? (vfat/ntfs) +uid=n, gid=n - set uid and gid for files on system (vfat/ntfs) +umask/dmask/fmask=nnn - masking of fs nodes (vfat/ntfs) + umask - user file creation, dmask - directory, fmask - files + +gettydefs +========= + +group +===== +group1::24:user1,user2 +----- +Simple format. name:password:gid:members + +host.conf +========= +# order can be any or all of bind (name server), hosts (hosts file), or nis +# this determines the order in which these are tried +order bind hosts nis +# multi can be on or off and determines if a host can have multiple IPs in hosts +multi on +# check if an IP is associated with a hostname given. can be on or off +nospoof on +# spoof attempts (above) log message to the syslog facitilty. on or off. +alert off +# domain name to remove from hostnames before lookup +# for example, aegis.example.com would become aegis with this setting. +trim example.com + +hosts +===== +# IP_address hostname1 hostname2 +127.0.0.1localhostloopback +::1localhost + +hosts.allow/deny +================ +ALL: ALL +ALL: ALL EXCEPT 192.168.0.125 +ALL: 192.168.1.0/24 +ALL: LOCAL +ALL: .example.com +ALL: .example.com EXCEPT testing.example.com +sshd: LOCAL +sshd, in.ftpd: LOCAL +in.ftpd: KNOWN +---------------- +There's more than this, but this is a good start to talk about. It's +service: host. ALL matches everything, either all services or all hosts. +You can use EXCEPT to add an exception. You can use subnet masks like good +old 192.168.0.0/16. You could also use LOCAL for all on the local subnet. +You can also specify domain names, including as exceptions. You can specify +specific daemons, like sshd here. You can also do multiple for one rule. If you +prefix in., it's specifically for incoming traffic. Finally, there's the +wildcards KNOWN, UNKNOWN, and PARANOID, which are for known hostnames, unknown +hostnames, and hostnames that are spoofed. There's also apparently command +expansiona and all that, but we'll cross that bridge when we get to it. + +hosts.lpd +========= ++ +hostname +-hostname ++@netgroup +-@netgroup +--------- ++ alone means any host on the network. hostname is a remote host allowed to +print on the local system. Add a - to forbid that. @netgroup is an NIS netgroup. +- works the same for these. + +inittab +======= +id:2:initdefault:echo "Runlevel 2" +------- +Pretty simple. id is a unique identifier. Two characters, it seems. Next is +the runlevel. Multiple can be specified (i.e. 234). Action is how the process +is to be run. Options include respawn (restart the process if existing, do not +start if not started), wait (start the process, wait for it to stop), once +(start process, do not restart on termination), boot (only start on boot), +bootwait (like wait, but only on boot), powerfail (only on SIGPWR), powerwait +(like wait, but only on SIGPWR), off (if started, send SIGTERM, wait 5 seconds, +then kill the process with SIGKILL), initdefault (used to determine default +runlevel), sysinit (executed before attempts to access console, processes are +executed and waited for termination of). + +issue +===== +We'll need something good to go here. I'll work it out later. + +ld.so.conf +========== +/usr/include +/home/user1/builds/include +---------- +Just a list of directories. Simple enough. + +motd +==== +We may or may not do this, since we'll have an issue file. + +mtab +==== +/dev/sda1 / fxfs rw,exec,suid,dev,async,nouser 0 0 +/dev/sdb1 /mnt ext4 rw,nosuid,nodev,user=user1 0 0 +---- +It's fstab but only the currently mounted filesystems. Simple enough. + +passwd +====== +user1:x:1001:24:GECOS field:/home/user1:/bin/sh +------ +username:password:uid:gid:gecos field:home directory:login shell +Password is stored in /etc/shadow. x is a placeholder for that. +gid is the primary group for the user. Files created by this user have this gid. + +printcap +======== +lw|LaserWriter:lw=/dev/ttya:br#9600:ms=-parity,onlcr,ixon,decctlq:\ +sd=/var/spool/lw:lf=/var/spool/lp-log:mx#0 +-------- +There's a lot to dissect here, and it's probably best to save that dissection +for a proper man page. Long story short, it's a series of options separated by +colons. The first option is name and aliases. Everythings else is options that +we'll need to specify in the man page. It's kinda like the termcap database, +though. So, yeah. + +profile +======= +It seems to be a shell script, basically. Fun. + +protocols +========= +ip0IP # internet protocol +--------- +It's basically official-name protocol-number alias. We'll need to find these. + +securetty +========= +/dev/tty0 +--------- +A list of ttys from which root can login. + +services +======== +ssh 22 SSH +-------- +Like protocols, but it's port instead of protocol. + +shadow +====== +user1:$id$salt$hash:7:7:21:14 +------ +username:crypt(3) output:days since pw change:til change allowed:\ +til change required:til expiration warning +For crypt(3) output, $id is the algorithm used, $salt is the salt used, $hash +is the outputted hash. + +shells +====== +/bin/sh +------ +Pathnames of shells. Simple enough. \ No newline at end of file diff --git a/notes/env_vars b/notes/env_vars new file mode 100644 index 0000000..9f957a8 --- /dev/null +++ b/notes/env_vars @@ -0,0 +1,96 @@ +Make primary +============ +ARFLAGS - flags for ar +CC - the default C compiler +CFLAGS - flags for cc +FC - the default FORTRAN complier +FFLAGS - flags for FORTRAN +GET - the program to use for SCCS get +GFLAGS - flags for get +LDFLAGS - flags for the linker +LEX - the default lexer +LFLAGS - flags for the lexer +MAKEFLAGS - default args for make +MAKESHELL - shell for make +PROJECTDIR - directory to search for SCCS files not in current directory +YACC - the default yacc implementation +YFLAGS - flags for yacc + +Environment +=========== +BROWSER - colon-separated list of browsers to try using for URLs +CDPATH - directories to use as a base for cd +COLUMNS - width for terminal screen/window +DATEMSK - template file for getdate() +DEAD - where mailx saves partial messages; defaults to ~/dead.letter +DISPLAY - default display for X11 programs +EDITOR - default text editor +ENV - a script to execute when starting sh interactively +EXINIT - commands to execute when starting ex +FCEDIT - the default value for sh's -e option +HISTFILE - file for terminal history +HISTSIZE - number of lines in the history file +HOME - home directory +IFS - characters used for field splitting, * expansion, and the read utility +LD_LIBRARY_PATH - directores to search for shared objects +LIBPATH - alternative for LD_LIBRARY_PATH +LINENO - line number in script before executing a command +LINES - height of terminal screen/window +LISTER - the command mailx uses when the folders command is given +LOGNAME - the user's login name +LPDEST - printer to use for lp +MAIL - the path of the user's mailbox +MAILCHECK - how often mail should be checked by sh +MAILPATH - where something mail-related is kept +MAILRC - mail configuration file +MANPATH - where man pages are +MBOX - where mailx saves read messages +MORE - default options for more (string of command line arguments) +MSGVERB - message components for fmtmsg() +OLDPWD - working directory before the last cd operation +OPTARG - used by getopts for argument storage +OPTERR - used by some getopts implementations for error stuff +OPTIND - used by getopts as the index of the next argument to parse +PAGER - the default output filter/paginator; defaults to more +PATH - where to look for executables +PBS_DPREFIX - default prefix for directives for qsub +PPID - parent process ID for the current shell +PRINTER - secondary printer to use for lp +PS1 - interactive prompt for shell +PS2 - continuation prompt for shell (i.e. for lines broken by \) +PS3 - prompt used for select loops in scripts +PS4 - prompt for script executed in debug mode +PWD - current working directory +RANDOM - generates a random number (from /dev/{u,}random?) +SECONDS - amount of time current shell has been around? +SHELL - preferrred command interpreter +TMPDIR - location for temporary files +TERM - terminal type for output +TERMCAP - tells system to use termcap rather than terminfo +TERMINFO - tells system to use terminfo rather than termcap +TZ - timezone +USER - alias for LOGNAME? +VISUAL - default visual text editor (subset of EDITOR) + +Localization +============ +LANG - language +LC_ALL - locale to use +LC_COLLATE - locate for collating order +LC_CTYPE - locale for character handling functions +LC_MESSAGES - language for messages +LC_MONETARY - locale for monetary values +LC_NUMERIC - locale for numbers +LC_TIME - locale for date/time formatting +NLSPATH - message catalogs + +Unknown (not in standard) +======= +These are only briefly referenced as things that compliant applications +should avoid conflicting with. I don't know what these do. +------- +CHARSET +HISTORY +MAILER +NPROC +PROCLANG \ No newline at end of file diff --git a/notes/fs_hierarchy b/notes/fs_hierarchy new file mode 100755 index 0000000..cbc768f --- /dev/null +++ b/notes/fs_hierarchy @@ -0,0 +1,259 @@ +/ - root directory +/bin - essential command binaries +/boot - bootup files +/dev - device files +/etc - configuration stuffs +/home - User home directories +/lib - essential libraries and kernel modules +/lib64 - 64-bit libraries (on amd64) +/media - removeable media mount point +/mnt - all-purpose mount point +/opt - add-on software packages +/root - root's home directory +/sbin - essential system binaries +/srv - web server stuffs (if we have a web server) +/tmp - volatile temporary files +/usr - user data +/var - variable data + +Stuff in /bin: +============== +cat +chgrp +chmod +chown +cp +date +dd +df +dmesg +echo +ed +false +hostname +kill +ln +login +ls +mkdir +mknod +more +mount +mv +netstat +ping +ps +pwd +rm +rmdir +sed +sh +stty +su +sync +tar +test and [ +true +umount +uname + +Stuff in dev: +============= +null - discards input, produces EOF when read from +zero - discards input, produces a bunch of \0 when read from +full - produces \0 when read from, generates ENOSPC when written to +random - a pseudorandom number generator (cryptographically secure) +urandom - a pseudorandom number generator (not cryptographically secure) +console - system console +stdin - standard input +stdout - standard output +stderr - standard error +ppp - PPP interface +lp* - line printers (e.g. lp0) +ptmx - psuedo-terminal controller +/pts/* - pseudo-terminals (e.g. /pts/0) +tty* - terminals (e.g. tty0) + ttyS* - serial port (e.g. ttyS0) + ttyUSB* - usb serial converter, modem, etc. (e.g. ttyUSB) +fb* - frame buffer (e.g. fb0) +fd* - floppy drive (e.g. fd0-fd7) +hd* - IDE hard drive (ATA drive/ATAPI CD drive) + hda - first channel primary drive + hdb - first channel secondary drive + hdc - second channel primary drive + hdd - second channel secondary drive + e.g. hda1 - first channel, primary drive, first partition +ht* - IDE tape (e.g. ht0), can prefix n for no-rewind +js* - joystick (e.g. js0), prefix d for digital instead of analogue (e.g. djs0) +md* - RAID (metadisk) (e.g. md0) +mouse* - Mouse (e.g. mouse0) +pp* - parallel ports (e.g. pp0) +nvme*n*p* - NVMe (drive controller, drive, partition) (e.g. nvme0n1p1) +mmcblk*p* - MMC (SD cards, etc.) (device, partition) (e.g. mmcblk0p1) +pd* - parallel port IDE devices (e.g. pda0 - first device, first partition) +ram* - ram disks (e.g. ram0) +rpda* - PDAs, like my Dell Axim (e.g. rpda0) +pt* - parallel port ATAPI tape device (e.g. pt0, npt0) +sd* - SCSI/SATA/USB/Firewire mass storage device + e.g. sda1 - first drive, first partition + ses* - enclosure driver (e.g. ses0) + sg* - generic SCSI layer (e.g. sg0) + sr* - ROM driver (optical disks) (e.g. sr0) + scd* - SCSI CD-ROM device, replaces sr* for this (e.g. scd0) + st* - magnetic tape (e.g. st0) + nst* - magnetic tape, no rewind (e.g. st0) + can suffix l, m, or a for modes 1, 2, or 3 (default is 0) +I kinda wanna change some things and remove some others. Like, some, I'll keep. +scd0? Yep. hda for ATA drives? Yep. lp, fb, fd, pp, nvme? Yep. I kinda wanna +split off USB and Firewire mass storage device. Not sure how. ud0 and fwd0, +maybe? Might remove pd for parallel port IDE devices and move PDAs to pda +instead of rpda. + +/etc hierarchy: +=============== +init.d - scripts for system initialisation +opt - config for /opt +rc[0-6].d - scripts for different runlevels +X11 - config for X (if we actually try to get graphics going) + +Stuff in etc: +============= +at.allow - users allowed to use at (doesn't exist by default) +at.deny - users not allowed to use at (exists empty by default) +fstab - static filesystem info +gettydefs? - getty settings? +group - list of groups +host.conf - resolver conf. file +hosts - static hostnames +hosts.allow - host access file for TCP wrappers +hosts.deny - host access file for TCP wrappers +hosts.lpd? - trusted hosts for lpd? +inittab - config file for init +issue - pre-login message/id +ld.so.conf - extra dirs for shared libraries +motd - message of the day +mtab? - dynamic filesystem info +passwd - password file +printcap? - lpd printer capability db? +profile - default sh init file +protocols - IP protocol listings +securetty - TTY access control for root login +services - port names for network services +shadow - shadow password file +shells - pathnames of login shells + +/media hierarchy: +================= +floppy - floppy drive (if present) +cdrom - cd drive (if present) +cdrecorder - cd writer (if present) +zip - zip drive (if, for some reason, present) + +Stuff for /sbin: +================ +shutdown +fastboot +fasthalt +fdisk +fsck +fsck.fxfs - fsck for the FENIX file system +halt +init +mkfs +mkfs.fxfs - make a FENIX file system +mkswap +reboot +swapon +swapoff +tty - the actual program that runs the TTY, not the minor utility +update + +/srv hierarchy: +=============== +ftp - ftp files +www - http files + +/usr hierarchy: +=============== +bin - user-facing commands +games - games. +include - C include files +lib - libraries +lib64 - 64-bit libraries (on amd64) +local - local hierarchy; safe from system updates + bin - local binaries + etc - config for local binaries + games - local game binaries + include - local C headers + lib - local libraries + lib64 - local 64-bit libraries (on amd64) + man - local online manuals + sbin - local system binaries + share - local arch-independent hierarchy + src - local source code +sbin - non-vital system binaries +share - architecture-independent files + calendar - files for calendar(1) + dict - word lists for look(1) + doc - documentation + games - files used by games + locale - locale info + man - online manuals + might have language subdirs i.e. man/en/man1, man/en_US/man1, etc. + might also have architechture subdirs i.e. man/en/man8/i386, etc. + man1 - user programs + man2 - system calls + man3 - library calls + man4 - special files + man5 - file formats + man6 - games + man7 - miscellaneous + man8 - system administration + misc - misc. systemwide files + ascii - file w/ ascii character set table + termcap/termcap.db - terminal capability database + nls - message catalogs for native lang support + terminfo - terminfo database + zoneinfo - tz info +src - source code +X11R6 - X11 release 6, if we need it + +/var hierarchy: +=============== +backups - system backups; probably don't touch, it's reserved +cache - app cache data + fonts - locally generated fonts + man - locally formatted man pages + www - www proxy/cache data + - package specific cache data +crash - crash dumps +cron - crontabs +games - variable game data +lib - variable state info + hwclock - state directory for hwclock (will we have hwclock?) + misc - misc. state data + xdm - X display manager var data (if we have this) + - editor backup files/state + - packaging support files + - state data for package +local - var data for /usr/local +lock - lock files + all files are of form LCK..* +log - logs + lastlog - last login of each user + messages - system messages + wtmp - record of logins and logouts +mail - mailbox files + all files are just usernames +msgs - reserved for...something? +opt - var data for /opt +preserve - reserved for vi crash saves +run - data for running processes +spool - app spool data + lpd? - printer spool? + printer - spool for given printer + mqueue? - outgoing mail queue? + news - news spool + uucp - uucp spool +tmp - temp files preserved between reboots +yp? - NIS database files? \ No newline at end of file diff --git a/notes/goals b/notes/goals new file mode 100755 index 0000000..763a441 --- /dev/null +++ b/notes/goals @@ -0,0 +1,8 @@ +My goals for FENIX have changed back to trying to make a fully POSIX-compliant +system. We may branch out a little, include some stuff from the old first +version of UNIX. We may also branch into the Linux Standard. We might write +out own package manager. Not sure yet. But the core of the system will be fully +POSIX-compliant. + +I want to make a system that I can get *certified* as UNIX. I don't just want +it to be "Fenris' UNIX*-like*". I want it to be "Fenris' UNIX". \ No newline at end of file diff --git a/notes/groups b/notes/groups new file mode 100644 index 0000000..cac8258 --- /dev/null +++ b/notes/groups @@ -0,0 +1,28 @@ +root (0) - complete system control +bin (1) - historical +daemon (2) - all system daemons with user accounts +tty (5) - access to ttys? +ftp (11) - has personal ftp (~/srv/ftp)? Can control ftpd? +mail (12) - ability to use usermail (/usr/bin/mail) +log (19) - access to /var/log +locate (21) - ability to use locate +http (33) - has personal site (~/srv/www)? Can control httpd? +games (50) - access to games (/usr/games, /var/games, etc.) +lock (54) - access to lockfiles +network (90) - access to network devices (lan, wifi, dial-up, etc.) +floppy (94) - access to floppy drives +scanner (96) - access to scanners +power (98) - ability to control power state of the system (e.g. shut it down) +users (985) - default user group +video (986) - access to video hardware (used for FENIX display server?) +uucp (987) - access to serial ports and connected devices +storage (988) - access to removable storage (usb drives, zip disks, etc.) +optical (990) - access to optical drives +lp (991) - access to printers and parallel port devices +input (993) - access to input devices other than keyboard +disk (994) - access to block devices not in floppy, storage, or optical + (this includes access to all hard drives) +audio (995) - access to audio devices +wheel (998) - administration; subsumes adm and log, has access to su +adm (999) - access to protected logs (i.e. kernel logs) +nobody (65534) - an unprivileged group \ No newline at end of file diff --git a/notes/important_daemons b/notes/important_daemons new file mode 100644 index 0000000..720d4d1 --- /dev/null +++ b/notes/important_daemons @@ -0,0 +1,20 @@ +This is not necessarily a complete list. We may add some, we may remove some. + +init - Self-explanatory. We're using SysV-style. +biod - NFS client daemon +crond - for cron jobs +dhcpd - for handling DHCP +fingerd - interface for the finger command and protocol +ftpd - FTP server +httpd - HTTP server +inetd - network connection requests +lpd - line printer daemon for print spooling +nfsd - NFS server daemon +ntpd - netword time sync +sshd - SSH server +sendmail - SMTP daemon +swapper/sched - manages swapping +syslogd - handles logging +syncd - keeps file systems synched with system memory +vhand - release pages of memory for other processes +ypbind - NIS daemon, basically \ No newline at end of file diff --git a/notes/libk stuff b/notes/libk stuff new file mode 100644 index 0000000..81f3265 --- /dev/null +++ b/notes/libk stuff @@ -0,0 +1,384 @@ +(Almost) all of this will be in libc as well, but this stuff should be a part +of libk (the libc makefile's FREE_OBJS variable). Anything not on this list +that the kernel will need that isn't otherwise a part of the libc is probably +best put in kernel dev, rather than in libc dev (e.g. info on the elf format +or endianness). This also isn't a complete list. This is based off what the +Linux klibc has that overlaps with what a POSIX-compliant libc has. We may need +to add more from the POSIX libc, and I may have not put in dependencies here or +there (types that are needed, or macros, or functions, or whatever). + +X - complete; ~ - prototype exists; ? - not sure if done +Unless otherwise specified, *() denotes a function, *[] an array variable, +* \* a pointer, [A-Z_0-9]+ a macro, [a-z_0-9] a variable or type, and anything +prefixed with struct is a struct. +(hello() is a function, hello[] is an array, hello * is a pointer, HELLO is a + macro, HELLO() is a function macro, hello is a variable or type, and + struct hello is a struct.) + +arpa/inet.h + inet_addr() + inet_ntoa() + inet_ntop() + inet_pton() +assert.h (complete) +ctype.h (complete as far as libk is concerned - don't need locale variants) +dirent.h + DIR type + struct dirent + alphasort() + closedir() + fdopendir() + opendir() + readdir() + dirrd() + scandir() +errno.h (complete) +fcntl.h + struct flock + open() + openat() + creat() + fcntl() + Neccesary macros for the above +fnmatch.h + X FNM_NOMATCH + X FNM_PATHNAME + X FNM_PERIOD + X FNM_NOESCAPE + ~ fnmatch() +grp.h + X struct group + ~ getgrid() + ~ getgrnam() +inttypes.h + imaxabs() + strtoimax() +limits.h (complete) +net/if.h +netinet/in.h +netinet/tcp.h +poll.h +pwd.h + struct passwd + getpwuid() + getpwman() +sched.h + struct sched_param + sched_setscheduler() + sched_yield() +setjmp.h + sigjmp_buf[] + setjmp() + longjmp() + sigsetjmp() + siglongjmp() +signal.h + sig_atomic_t + SIGRTMIN + SIGRTMAX + sigemptyset() + sigfillset() + sigaddset() + sigdelset() + sigismember() + signal() + sigaction() + sigprocmask() + sigpending() + sigsuspend() + raise() + kill() +stdarg.h + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +stdbool.h (complete) +stddef.h (complete) +stdint.h (complete) +stdio.h + X FILE type + X EOF + X BUFSIZ + X _IO*BF + X stdin, stdout, stderr + ~ fopen() + ~ fdopen() + ~ fclose() + ~ fseek() + ~ rewind() + ~ fputs() + fputs_unlocked() + X puts() + ~ fputc() + ~ putc() + X putchar() + fputc_unlocked() + putchar_unlocked() + putc_unlocked() + ~ fgetc() + fgetc_unlocked() + ~ fgets() + fgets_unlocked() + ~ getc() + ~ getchar() + getc_unlocked() + getchar_unlocked() + ~ ungetc() + X printf() + ~ vprintf() + ~ fprintf() + ~ vfprintf() + ~ sprintf() + ~ vsprintf() + ~ snprintf() + ~ vsnprintf() + ~ sscanf() + ~ vsscanf() + ? perror() + rename() + renameat() + remove() + ~ fread() + ~ fwrite() + ftell() + ~ ferror() + ~ feof() + fileno() + ~ clearrerr() +stdlib.h + X EXIT_FAILURE + X EXIT_SUCCESS + ? abort() + X abs() + ~ system() + ~ atexit() + ~ atoi() + ~ atol() + ~ atoll + ~ exit() + ~_Exit() + X labs() + X llabs() + ~ strtol() + ~ strtoll() + ~ strtoul() + ~ strtoull() + ~ getenv() + putenv() + setenv() + unsetenv() + X bsearch() + ~ qsort() + X srand() + X rand() + srand48() + jrand48() + mrand48() + nrand48() + lrand48() + random() + srandom() + unlockpt() + ptsname() + posix_openpt() + grantpt() + realpath() +string.h + memccpy() + memchr() + X memcmp() + X memcpy() + X memmove() + X memset() + X strcat() + ~ strchr() + X strcmp() + ~ strcpy() + X strcspn() + strdup() + ~ strerror() + strsignal() + X strlen() + ~ strncat() + ~ strncmp() + ~ strncpy() + strpbrk() + ~ strstr() + X strtok() + strtok_r() +sys/mman.h + mmap() + munmap() + shm_open() + shm_unlink() + msync() + mprotect() + mlockall() + munlockall() + mlock() + munlock() +sys/resource.h + getpriority() + setpriority() + getrusage() +sys/select.h + FD_CLR() + FD_ISSET() + FD_SET() + FD_ZERO() + FD_SETSIZE + select() + pselect() +sys/socket.h + X sa_family_t + X struct sockaddr + X socklen_t + struct msghdr + struct cmsghdr + CMSG_DATA() + CMSG_NXTHDR() + CMSG_FIRSTHDR() + accept() + bind() + connect() + getpeername() + getsockname() + getsockopt() + listen() + recv() + recvfrom() + recvmsg() + send() + sendmsg() + sendto() + setsockopt() + shutdown() + socket() + socketpair() +sys/stat.h + S_IFMT macro family + S_I[RWX](USR|GRP|OTH) and related macros + S_IS. macro family + stat() + fstat() + fstatat() + lstat() + umask() + mknod() + mknodat() + mkfifo() + utimensat() + fchmodat() +sys/statvfs.h + struct statvfs + fstatvfs() + statvfs() +sys/time.h + gettimeofday() + gettitimer() + settitimer() + utimes() +sys/uio.h + struct iovec + readv() + writev() +sys/un.h + ??? +sys/utsname.h + X struct utsname + ~ uname() +sys/wait.h + WEXITSTATUS() + WTERMSIG() + WIFEXITED() + WIFSTOPPED() + WIFSIGNALED() + WSTOPSIG() + X wait() + waitpid() +syslog.h + ~ closelog() + ~ openlog() + ~ syslog() +termios.h + TCSANOW + TCSADRAIN + TCSAFLUSH + tcgetattr() + tcsetattr() + tcflow() + tcflush() + tcdrain() + tcgetsid() + tcsendbreak() + cfgetospeed() + cfgetispeed() + cfsetospeed() + cfsetispeed() +time.h + X time() + ~ nanosleep() +unistd.h + X F_OK + X R_OK + X W_OK + X X_OK + STDERR_FILENO + STDIN_FILENO + STDOUT_FILENO + access() + chdir() + chown() + close() + dup() + dup2() + _exit() + execl() + execle() + execlp() + execv() + execve() + execvp() + faccessat() + fchdir() + fchown() + fchownat() + fdatasync() + fork() + fsync() + ftruncate() + getegid() + geteuid() + getgid() + getgroups() + gethostname() + getopt() + getuid() + isatty() + lchown() + link() + linkat() + lseek() + nice() + pipe() + pread() + pwrite() + read() + readlink() + readlinkat() + rmdir() + setegid() + seteuid() + setgid() + setuid() + sleep() + symlink() + symlinkat() + sync() + unlink() + unlinkat() + write() +utime.h + struct utimbuf + utime() \ No newline at end of file diff --git a/notes/notes on code standards and style b/notes/notes on code standards and style new file mode 100644 index 0000000..302130c --- /dev/null +++ b/notes/notes on code standards and style @@ -0,0 +1,543 @@ +Intellectual property +===================== + +Regarding proprietary programs: + +Don't reference them. We don't need to get in trouble. + +Regarding free programs: + +Be careful referencing them, especially if they use a GPL-style license. I +don't need that fucking licensing nightmare getting dragged into this. If it +uses a 0BSD-style license, you can freely reference it, even copy it. I just +ask that you properly credit the original. + +Trademarks: + +Don't bother with acknowledgements. Just make sure it's written in a way to +not be mistaken for our own trademark. + +Program design +============== + +Which language: + +C. We use C around here. It's honestly the only language I'm still comfortable +with. I'm out of practice with anything else. Though, for what we do here, C is +kinda the most suitable language we have anyways. + +In particular, though, of what I'm even familiar with, I don't like +object-oriented programming, so no C++ or Java. Java's too bloated anyways. +Same for Clojure. FORTRAN's not really useful here, though I do want to have +a library for FORTRAN. And Prolog is really only useful as a proof language. +So, really, C is the only thing I want to use (except where we need asm). + +Compatibility: + +We do compatibility here. Current, we're working off POSIX/the Single UNIX +Specification, the ISO C standard, and the Filesystem Hierarchy Standard. +Everything implemented should *not* conflict with these standards. We can add +things here and there, where needed or where it might be fun. But anything added +should either be something not specified by the standard (like the init system) +or that is otherwise optional, e.g. a game. + +Non-standard features: + +Don't use them. For instance, don't use any GNU C extensions. You should be +writing standard compliant code. Specifically, we use `-std=c99`. + +More on C standards: + +We use C99. However, there are some exceptions. For instance, we never use +single-line comments (//). Instead, we always use block comments (/* */). + +Other things not to do include using trigraphs (why do those even still exist?) +and writing anything in pre-standard style. + +Conditional compilation: + +I guess use if statements in functions where possible. Outside of functions, +of course, use #if/#ifdef/#ifndef. In general, that's what you should do. + +Writing Programs +================ + +Standards: + +We obey POSIX around here. We want to implement all stuff found in the standards +referenced above. We don't want to deviate where it matters. Where does it +matter? Well, if the standard has something to say about it, it matters. For +instance, the POSIX standard specifies that cat has the following form: + cat [-u] [file...] +Don't add shit to that. We don't need `cat -v`. + +If the standard doesn't have something to say, then consider the following: + 1. Are we considering implementation details? + 2. Is this optional, insofar as it's just a program that a user might install? +In the first case, for instance, POSIX doesn't say how printf should do its +thing. It says what printf needs to support (format specifiers, etc.) and what +results it should put out, but it doesn't specify the internals. It's a black +box. Here's what goes in, here's what goes out. What happens in the middle? +That's up to us to decide. Anything like that is fair game. POSIX and SUS don't +specify the initialization process/sequence for a UNIX system. Thus, how we +actually start up the system, our init program, is completely up to us. + +In the second case, just make sure it's optional. Don't make it a key part of +the system. Like, if we were to add a COBOL compiler, don't make it important. +You should be able to remove the COBOL compiler from the system without it +breaking things. It should basically function like a software package that the +user'd install themselves. (In fact, you may just want to make it an installable +software package.) Do keep in mind for this kind of stuff, if there's a +standard, you should probably follow it. Like, if we do a COBOL compiler, follow +the COBOL standards. Please. + +Robustness: + +In general, arbitrary limits should be avoided. In general, try to accommodate, +e.g., long file names. It's okay to use, say, limits.h to get a limit for +something like path name lengths, but try to not do something like that, to have +a cap on that kinda stuff. + +Keep all non-printing characters found in files. Try to support different +locales and character encodings, like UTF-8. There should be functions to help +you deal with that stuff. + +Check for errors when making calls, especially system calls. In cases of errors, +print a fucking error message. Nothing is more frustrating for an end user than +having something fail and not being told why. (This was frustrating for me +during my first attempt at moving FENIX's kernel to the higher half. grub-file +tells you whether it's a valid multiboot header but not why it fails if it +isn't. I still have no clue why it wasn't working.) + +Check memory allocation calls (malloc, calloc, realloc) for NULL return. Don't +just assume it allocated successfully. Be careful with realloc. Don't just +assume it's going to keep stuff in place. + +If you call free, don't try to reference that memory again. Assume that the +moment you free'd it, something else immediately snapped that memory up. + +If a malloc/calloc/realloc fails, that should be a fatal error. The only +exception should be in the login shell and related important system processes, +like TTY. If those have failed calls, that needs to be dealt with somehow. +After all, these are important bits. So, I don't know quite how to deal with +that, but definitely keep that in mind. + +When declaring variables, most should be immediately initialized. For instance, +if you create a variable for a flag, it should be initialized to a sane default. +For example, if you want a flag for "hey, use this option", it should be +initialized to whatever the default should be (off or on). This is especially +important for static variables, which may be referenced by a different call +without it being initialized, which would be bad! + +In the case of impossible conditions, print something to tell the user that +the program's hit a bug. Sure, someone's going to have to go in with the source +and a debugger and find that bug, but at least let the user know that a bug's +occurred. That way, the program doesn't just stop and they have no idea why. +You don't need to give a detailed explanation (though you may want to give some +info that might be useful to someone who wants to debug), but at least give +them something like "Oops, we've hit a bug! Killing ..." so they know +that what they tried to do led to a bug. + +For exit values, don't just use error counts. Different errors should have +different error values. In general, the POSIX standard will give you an idea +of what error values matter, and you can define others as they're needed. + +For temporary files, you should generally put them in /tmp, but probably have +some way for the user to tell the program where they might actually want temp. +files to go. Check TMPDIR, maybe? (By the way, be careful with this stuff. You +might hit security issues.) + +Library behaviour: + +Try to make functions reentrant. In general, if a function needs to be +thread-safe, it'll be reentrant, but even if it doesn't, it's not the worst +idea to make it reentrant. Even dynamic memory, though if it can't be avoided, +then so be it. + +Also, some naming convention for you: + - If it's a POSIX function/macro/whatever, use that name + - Structs should be struct posix_name, not just posix_name + - If it's a function/whatever for making something work, start it with a _ + - For instance _do_thing() + +Basically, if it's not supposed to be user-facing, start it with _. Otherwise, +use a normal name, probably with one given in the standard. + +Formatting error messages: + +In compilers, use give error messages like so: + :: +Line numbers start from 1. + +If it's a program, tell give an error message that tells the user the program +and the issue. You'll probably want to also include a PID. For example: + (): + +You might be able to get away with omitting the program and PID. + +Interface standards: + +Don't make behaviour specific to the name used. Even if we were to add GNU awk +compatibility to our awk implementation, don't make whether it uses GNU awk +mode dependent on whether you call awk or gawk. Make it a flag. In general, +though, this probably won't be an issue. + +Don't make behaviour dependent on device. For instance, don't make output +differ depending on whether we're using a VTTY or a proper physical TTY. Leave +the specifics to the low-level interfaces (unless, of course, you're working on +those low-level interface, in which case you should do what you need to do). +The only exception is checking whether a thing is running interactively before +printing out terminal control characters for things like color. Like, in cal, +someone may just want to redirect that into a file. It shouldn't include the +codes used to change the color of the current day. Also, if you're outputting +binary data, maybe don't just send it to stdout. Ask, probably. + +Finding executable and stuff: + +Start with argv[0]. If it's a path name, it should be basename(argv[0]). + +That's all I have to say, really. + +GUIs: + +We're not really concerned about them at this point in time. When we get to +that, we're gonna probably be running off the X Window System. We'll probably +have our own WM/DE. But, again, we're not worried about that right now. Right +now, we're focused on just getting the console level stuff up. + +CLIs: + +Follow POSIX guidelines for options. I've broken this next rule quite a bit, +but maybe make use of getopt() for parsing arguments, instead of what I've been +doing in manually searching for them. + +We're not doing long-named options. The idea is nice, but for now, we're +sticking with the POSIX standard. Maybe we'll add 'em in one day. (I mean, I +guess we could use them in non-POSIX utilities, but still.) + +Memory usage: + +Try to keep it reasonably low. Obviously, we don't need to keep it that low, but +don't go using all the RAM just to print out a message. + +Valgrind's not the worst tool to play with. You might not need to worry about +all the messages it gives, but in general, try to keep it quiet, unless that +would really fuck up things otherwise. In other words, if it bitches at you +about not freeing up memory before exiting, add in the necessary free()s. + +File usage: + +In general, /etc is where configuration for system-level stuff goes. Runtime +created files should go in /var/cache or /tmp. You can also use /var/lib. +Files may be stored in /usr, but be prepared for a read-only /usr. Don't assume +you can write to /usr. + +Style and other important things about C +======================================== + +Formatting: + +Keep lines to 80 characters or less (especially since FENIX currently only +supports 80 character lines). + +The open brace for any code block should go on the line where it starts. + int main(void) { + if(test) { + do{ + } while(test); + } + } + +There should be a space before any open brace or after any close brace (if +something follows said close brace). + +Keep any function definitions to one line. Like this: + int main(void) +not: + int + main(void) +If a function definition is longer than 80 character, you are allowed to split +it. + +For function bodies, use the following standards: + +No space between function/keyword and paren. Like this: + int main(void) + if(test) + for(int i = 0; i < 10; i++) + printf("Hello, World!\n"); + +When splitting expressions, split after the operator: + if(condition1 && condition2 && + condition3) + +Do-whiles, as hinted at above, should have the end brace and while on the same +line, like so: + do { + thing(); + } while(test); + +For indentation, spaces, 2 spaces specifically. And, yeah. Use your brain on +how to actually use that. (The exception to this rule is makefiles, which +require tabs and a specific indentation style. Look up more on makefiles for +that information.) + +Comments: + +Try to start programs and headers with a description of what it is. For example, +from stdlib.h: + /* + * - standard library definitions + * + * This header is a part of the FENIX C Library and is free software. + * You can redistribute and/or modify it subject to the terms of the + * Clumsy Wolf Public License v4. For more details, see the file COPYING. + * + * The FENIX C Library is distributed WITH NO WARRANTY WHATSOEVER. See + * The CWPL for more details. + */ + +In general, it should say what the file/program is, what it does, and include +that free software, no warranty header. + +Try to write comments in english, but if you can't then write it in your native +language. I'd prefer you use english, since that's my native language. I also +kinda understand spanish and know a small bit of danish. But, if you can't do +english or spanish, write in what you know. Just romanize your comment. For +instance, if you're writing in japanese, please use romaji instead of normal +japanese script. Otherwise, things get weird. + +Probably not the worst idea to have a comment on what functions do, but don't +feel like you *need* to add them, especially if the function has a sensible +name. Like, if they function is called do_x(), you don't need a comment that +says that it "Does X". + +Please only use one space after a sentence. It'll annoy me otherwise. Also, use +complete sentences, capitalize sentences unless they start with a lowercase +identifier, etc., etc. + +When commenting code, try not to comment the obvious. In general, if you need +to have a comment on what a variable does, you need to re-name the variable. +If you need to comment on what a block of code is doing, consider whether it +needs to be that complicated or if you can simplify it. This isn't always true, +but in general, try to keep to that rule of thumb. + +Using C constructs: + +Always declare the type of objects. Explicitly declare all arguments to +functions and declare the return type of the function. So, it's `int var`, not +just `var`, and it's `int main(void)`, not `main()`. + +When it comes to compiler options, use -Wall. Try to get rid of any warnings you +can, but if you can't, don't fret about it. + +Be careful with linting tools. In general, don't bother with them, unless you +think it'll help with a bug. Don't just run linting tools, though. Like, you +generally don't need to bother casting malloc(). If your tool is telling you +that you need to, you can probably ignore it. + +extern declarations should go at the start of a file or in a header. Don't put +externs inside function if you can avoid it. + +Declare as many variables as you need. Sure, you can just carefully reuse the +same variable for different things, but it's probably better to just make +another variable. (The exception to this rule is counters like i, j, etc, +unless you specifically need to preserve the value of one of them.) + +Avoid shadowing. If you declare a global variable, don't declare local variables +with the same name. + +Declarations should either be on the same line or in multiple declarations. +So, do this: + int foo, bar; +Or this: + int foo; + int bar; +Not this: + int foo, + bar; + +In if-else statements, *always use brackets*. Please. It makes it much clearer +as to what belongs to what. It'll keep you from ending up in a situation where +you've accidentally got a function call outside of an if-statement that should +actually be inside it. Also, single line else if. + +Typedef your structs in the declaration. Basically, your structure declarations +should probably look like this: + typedef struct _f_foo { + /* Stuff goes here */ + } foo; + +Names: + +Don't be terse in your naming. Give it a descriptive english name. Like, name +it `do_ending_newline`, not just `d`. + +If it's only used shortly for an obvious purpose, you can ignore this. Like, +you can continue with for(int i = 0...). You don't need to name that variable +something else like counter. We're programmers. We know what i is used for. + +Try not to use too many abbreviations in names. You can if you need to, but +you should try not to. + +Use underscores to separate words in identifiers (snake_case), not CamelCase. + +If a variable is supposed to be a command-line flag, maybe include a comment +for what option it's supposed to be (i.e. /* -b */). If your flags are those +kinda octal things (04 for -x, 02 for -y, 01 for -z), definitely include a +comment on what corresponds to what (/* 04: -x, 02: -y, 01: -z */). + +For names with constant values, you can probably decide on your own whether it's +better to use an enum or #define. If you use a #define, the name should be in +all uppercase ("DEFINE_CONST"). Enums should use lowercase ("enum_const"). + +For file names, I guess try to keep them short (14 characters), but don't feel +like you need to. It's not the worst idea for working with older UNIXes. Just +don't feel the need to be compatible with DOS 8.3 filenames. We don't care about +Microsoft's shit. Just other UNIXes. + +Portability: + +FENIX doesn't necessarily need to be portable, but should be portable purely +as a result of being completely to standard. So, our programs should be able to +run on any system that is standards compliant. + +In general, you should use features in the standard. Don't try to write an +interface in a program if you can just use an interface in POSIX. Again, if +you're doing kernel or libc dev, you can kinda fudge this, but for util dev, +definitely use the standard interfaces. + +Don't worry about supporting non-UNIX systems. Windows? Don't worry about it. +If you can do something using pure ISO C, then it doesn't hurt, but don't +overcomplicate it if you can just use a POSIX function instead. + +Porting between CPU: + +For a start, we're not worried about anything not 32-bit or higher. 16-bit? +Not a concern. In general, though, anything architecture dependent should be +in an arch dir. So, the actual low-level kernel code? arch/i386 (or whatever +arch you're writing for). + +In general, assume that your types will be as defined in limits.h. + +Don't assume endianness. Be careful about that stuff. + +Calling system functions: + +Just call the POSIX functions. Use standard interfaces to stuff. + +Internationalization: + +Um. Not sure how to handle this right now. If you want to port into another +language, get in touch. + +Character set: + +Try to stick to ASCII. (This is why I asked for romaji earlier.) + +If you need non-ASCII, use UTF-8. Try to avoid this if possible. + +Quote characters: + +Be careful. Quotes are 0x22 ('"') and 0x27 ('''). Don't let your computer fuck +that stuff up. + +If you're internationalizing, though, use the right quotes for stuff. Like, in +French, you'd want «». + +mmap: + +Don't assume it works for everything or fails for everything. + +Try it on a file you want to use. If it fails, use read() and write(). + +Documentation +============= + +Man pages: + +The primary method of documenting stuff for FENIX is in the man pages. All else +is secondary. Man pages should have a fairly standard format of: + Title + Synopsis + Description + Options + Examples + Author + Copyright + +The title is fairly basic. Name the thing and give a short description. For +instance: head - copy the first part of files. + +The synopsis is just a listing of how the program works. So, for head, it's + head [-n number] file ... +Any optional arguments should be in square brackets. Mutually exclusive options +should be in the same brackets separated by pipes ([-s|-v]). Options that don't +take a further parameter (unlike -n in the above example) can be grouped +togethers if the software can take them that way ([-elm] for you can do -e, -l +and/or -m, -el, -lm or -em, or -elm). Variable type stuff, like file or number +should be """italicized""" (/fIvariable/fR). If you want to note that you can +repeat the last argument, e.g. take multiple files, use ellipses. + +Description should give a full description of how it works. Tell what it does, +note any oddities or behaviour to be noted, and give a quick rundown of how +options change things. + +Options should list each option one by one and explain it in detail. + +Examples should give at least one example of how to use it and what the example +would do. + +The author should be whoever wrote the program. List the original author(s). +So, you may notice plenty of utils have the author as "Kat", since I, Kat, am +the one who wrote them. + +Copyright should contain the following: + Copyright (C) 2019 The FENIX Project + + This software is free software. Feel free to modify it + and/or pass it around. +A lot of older man pages will list the copyright as: + Copyright (C) 2019 Katlynn Richey +Not the worst idea to update that if you see it. + +You might also want to include the package of a thing, if it's got one. For +example, utilities include: + This implementation is a part of the fenutils package. + +Physical manual: + +The secondary documentation is the manual written in roff. Practically, it +documents the same kinda things. Name, synopsis, options, etc. It also includes +some other stuff, like See Also, for related stuff; Diagnostics, for what all +errors it can produce; and Bugs, for any bugs in a program. Additionally, the +author field is different, and the details for that, along with other bits, +can be found in the Intro. + +License for the manuals: + +The manuals are tentatively under CC-BY. Maybe I'll write my own license, like +with the CWPL. For now, though, it's CC-BY. + +Credits: + +In man pages (including physical), include the original author of the program, +not the author of the man page. (Generally, you should be writing the man +pages yourself anyways.) + +On the title page of the physical manual, all the folx behind the project should +be named. For now, this is fairly small. If it gets too big, we'll give them +all credit within the first few pages and have the author on the manual as +"The FENIX Project Manual Team". + +On other manuals: + +Don't copy other people's manuals wholesale. Try to write it yourself. The +exception is in working with the POSIX standard. Don't copy that wholesale, but +you can base your man page on the relevant POSIX page. Just know that the +POSIX page probably won't give you a complete man page! + +Releases +======== + +I'll worry about that later. \ No newline at end of file diff --git a/notes/runlevels b/notes/runlevels new file mode 100644 index 0000000..87048ee --- /dev/null +++ b/notes/runlevels @@ -0,0 +1,8 @@ +0 - shutdown system, power-off hardware +1 - Single-user mode + Only mounts / +2 - Multi-user mode +3 - Multi-user mode with networking +4 - Multi-user mode; Boot to X/FENIX display server +5 - User-definable? Reboot to firmware on UEFI? +6 - Reboot \ No newline at end of file diff --git a/notes/stuff we gotta do ourselves b/notes/stuff we gotta do ourselves new file mode 100644 index 0000000..3e79fe1 --- /dev/null +++ b/notes/stuff we gotta do ourselves @@ -0,0 +1,68 @@ +There's a lot that the SUS doesn't define, stuff that's up to us. This is a list +of some of that stuff. + +Stuff it doesn't include: +========================= + +Tools specifically use for for development. The development tools are, according +to the Guide to the Single Unix Specification, intended for the installation, +not development of debugging. This includes stuff like debuggers, assembly +language tools (like as), and program style tools (like linters). There can +be standards for this sort of thing (things that a linter might want to include, +assembly language definitions like the x86 assembly standard, etc.), but it's +not in the SUS. So, if we want to include any of these, we gotta do 'em +ourselves. + +Stuff that isn't "useful to conforming applications"/"from shell scripts or +typical application programs" This is a lot of user-facing stuff that they'd +use interactively and that can't be used from, like, a shell script and that +isn't useful for any of the goals of the SUS. For example, news and calendar +are listed this way. I definitely want those. I may also include a music player, +assuming I can figure that out. And, of course, other, similar applications, +like web browsers, RSS readers, etc. Stuff that we can just include if we want. + +Things that might have been replaced. Specifically, I'm talking about cpio and +tar. Those were removed in favour of pax, but we still probably want those lying +around. + +Things that have been subsumed by other applications. Sure, cpp and ld might be +a part of c99, but we probably still want those around separately, even if it's +just breaking the rule ("rule", guideline) that what a program does shouldn't be +determined by how it was invoked. (i.e. We just make c99 behave with linking +flags if started as ld and with compiling C++ flags if started as cpp.) + +"Terminal-oriented" or otherwise low-level programs. Things like login, passwd, +chroot, or su. These are things we're gonna need but that the SUS doesn't touch. +(Oh, and wall.) + +mknod. It's only excluded for being too implementation-defined, but we still +probably want it. + +Graphical interfaces. Curses is part of the SUS, but anything beyond that +(X servers, the actual interfaces that run on said servers) is up to us (at +least to the extent there isn't a standard; we can't just write our own graphics +server and call it X11). + +Anything on the system level. XSH defines a lot of interfaces to that system +level stuff, and I think there are a few more utilities that do that interfacing +in XCU, but the kernel level stuff they reference is up to us. This includes +how we do scheduling (niceness notwithstanding), memory allocation (as called +through the malloc family), interrupts, hard disk stuff (including the file +system), and more. + +dump, an old backup program. Fun stuff. + +Stuff the standard mentions probably needing: +============================================= + +Text formatting. I'd put my money on troff, but we could do TeX. The POSIX +standard mentioned work in the area of SGML could help, as this is something +they feel they don't have but need, and the FHS mentioned SGML directories, so +we could do SGML (though I think I'd rather do troff). + +More control over printing. Specifically, I think we're gonna have an lpd, +instead of lp just going straight to the printer, so we could have control over +scheduling (and even cancelling) print jobs. We could also probably put in some +stuff to help with formatting print jobs. + +Tools for working in other programming langauges besides C and FORTRAN. \ No newline at end of file diff --git a/notes/tentative_dev_timeline b/notes/tentative_dev_timeline new file mode 100644 index 0000000..5a32829 --- /dev/null +++ b/notes/tentative_dev_timeline @@ -0,0 +1,42 @@ +X Get a kernel that can draw to screen + Higher half? + Paging +X Get GDT setup +- Enter protected mode + *THIS IS A BOOTLOADER THING. GRUB DOES THIS FOR YOU.* +X Get interrupts working + Get the PIT working, especially IRQ0 + HPET can come later + Multitasking/Scheduler (with niceness) + Get memory mapping up + Get a memory manager going + Setup a heap + Multithreading support + Hardware abstraction layer + Get IRQ1 (keyboard) working + Get a basic debug/rescue shell working + Get IRQ8 and IRQ14 working + Get a hard drive driver working (with UNIX/MINIX-esque file system driver) + Get the basic init system set up + Add userspace stuff to GDT, including TSS + Get the C lib. program initialization set up + Get a program loader working + Get necessary C lib. stuff for vsh working + Get vsh loading + Get other interrupt handlers set up + Add utils into build tooling alongside kernel and libc + Get the TTY properly set up + Get curses going + Get core utilities (and requirements) finished + Get vsh finished (fully sh-compliant), including built-ins + Get rc-based init going + Get multiuser support (/etc/passwd, etc.) + Add networking support + Finish the C library + Add amd64 and EFI support + Get misc. and XSI utilities working + Get complex utilities working + Get the C toolchain working + Get multiuser utils finished + Get dev utils working + Get SCCS working \ No newline at end of file diff --git a/notes/util_cats b/notes/util_cats new file mode 100644 index 0000000..4145b64 --- /dev/null +++ b/notes/util_cats @@ -0,0 +1,224 @@ +Core - These go in /bin +======================= +at +batch +X cat +chgrp +chmod +chown +cp +crontab +dd +df +dmesg +du +X echo +X false +file +find +getconf +grep +hostname +X ln +logger +login +ls +mkdir +X mkfifo +mknod +mount +mv +netstat +newgrp +nice +nohup +pathchk +ping +printf +ps +renice +rm +X rmdir +sh +X sleep +stty +su +sync +tar +X tee +time +touch +tput +X true +X tty +umount +X uname +xargs + +Important system stuff - These go in /sbin +========================================== +shutdown +fastboot +fasthalt +fdisk +fsck (especially fsck.fxfs) +halt +init +mkfs (especially mkfs.fxfs) +mkswap +reboot +swapon +swapoff +update + +Shell built-ins - These may or may not have standalone versions +=============================================================== +alias +bg +~ cd +command +env +fc +fg +getopts +hash +jobs +X kill +pwd +read +tabs +test +type +ulimit +umask +unalias +wait + +C toolchain - Stuff used for C language development +=================================================== +ar +awk +cc/c99 +cflow +cxref +lex +yacc + +XSI - X/Open Source utilities +============================= +cal +compress +date +fuser +ipcrm +ipcs +X link +nl +uncompress +unlink +zcat + +SCCS +==== +admin +delta +get +prs +rmdel +sact +sccs +unget +val +what + +Dev utils - General development utilities (not C-specific) +========================================================== +asa +ctags +fort77 +gencat +m4 +make +nm +od +patch +pax +strip + +Complex - Utilities that will be difficult, might need lex/yacc or curses, etc. +=============================================================================== +bc +ed +ex +expr +join +lp +mailx +more +pr +sed +vi + +Multi-user - Utilities for multi-user interactions and the like +=============================================================== +id +X logname +mesg +talk +who +write + +Obsolete batch job commands +=========================== +qalter +qdel +qhold +qmove +qmsg +qrerun +qrls +qselect +qsig +qstat +qsub + +Miscellaneous +============= +X basename +X cksum +X cmp +comm +csplit +cut +diff +X dirname +X expand +fold +X head +iconv +locale +localedef +locate +look +man +paste +sort +split +strings +tail +tr +tsort +unexpand +uniq +uucp +uudecode +uuencode +uustat +uux +X wc + +Additions - Things not in any standard +====================================== +basic (bas?)??? +cobol +dump \ No newline at end of file diff --git a/qemu.sh b/qemu.sh new file mode 100755 index 0000000..26ec678 --- /dev/null +++ b/qemu.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e +. ./iso.sh + +qemu-system-$(./target-triplet-to-arch.sh $HOST) -cdrom fenix.iso diff --git a/target-triplet-to-arch.sh b/target-triplet-to-arch.sh new file mode 100755 index 0000000..8e16df5 --- /dev/null +++ b/target-triplet-to-arch.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +if echo "$1" | grep -Eq 'i[[:digit:]]86-'; then + echo i386 +else + echo "$1" | grep -Eo '&[[:alnum:]_]*' +fi