├── .clang-format ├── .clang-tidy ├── .github └── workflows │ ├── documentation.yml │ └── ubuntu.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── doc ├── .gitignore ├── doxygen.css ├── scan_codes_it.md ├── signal.md └── syscall.md ├── exercises └── ipc_messaging.md ├── files ├── README.md ├── etc │ ├── group │ ├── hostname │ ├── issue │ ├── motd │ ├── passwd │ └── shadow ├── home │ └── user │ │ ├── .shellrc │ │ ├── README.md │ │ ├── root │ │ ├── tmp.md │ │ └── welcome.md ├── root │ └── .bashrc └── usr │ └── share │ └── man │ ├── cat.man │ ├── cd.man │ ├── chmod.man │ ├── chown.man │ ├── clear.man │ ├── cp.man │ ├── cpuid.man │ ├── date.man │ ├── echo.man │ ├── env.man │ ├── false.man │ ├── head.man │ ├── hier.man │ ├── id.man │ ├── init.man │ ├── ipcs.man │ ├── kill.man │ ├── login.man │ ├── ls.man │ ├── man.man │ ├── mkdir.man │ ├── more.man │ ├── passwd.man │ ├── rmdir.man │ ├── shadow.man │ ├── shell.man │ ├── showpid.man │ ├── sleep.man │ ├── stat.man │ ├── touch.man │ ├── uname.man │ └── uptime.man ├── iso └── boot │ └── grub │ ├── grub.cfg │ └── grub.cfg.runtests ├── libc ├── CMakeLists.txt ├── inc │ ├── array.h │ ├── assert.h │ ├── bits │ │ ├── ioctls.h │ │ ├── stat.h │ │ └── termios-struct.h │ ├── crypt │ │ └── sha256.h │ ├── ctype.h │ ├── dirent.h │ ├── err.h │ ├── errno.h │ ├── fcntl.h │ ├── grp.h │ ├── hashmap.h │ ├── io │ │ ├── ansi_colors.h │ │ ├── mm_io.h │ │ └── port_io.h │ ├── libgen.h │ ├── limits.h │ ├── list.h │ ├── list_head.h │ ├── list_head_algorithm.h │ ├── math.h │ ├── ndtree.h │ ├── os_root_path.h │ ├── pwd.h │ ├── readline.h │ ├── ring_buffer.h │ ├── sched.h │ ├── shadow.h │ ├── signal.h │ ├── stdarg.h │ ├── stdbool.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── strerror.h │ ├── string.h │ ├── sys │ │ ├── bitops.h │ │ ├── ioctl.h │ │ ├── ipc.h │ │ ├── kernel_levels.h │ │ ├── mman.h │ │ ├── msg.h │ │ ├── reboot.h │ │ ├── sem.h │ │ ├── shm.h │ │ ├── stat.h │ │ ├── types.h │ │ ├── utsname.h │ │ └── wait.h │ ├── syslog.h │ ├── system │ │ └── syscall_types.h │ ├── termios.h │ ├── time.h │ └── unistd.h └── src │ ├── abort.c │ ├── assert.c │ ├── crt0.S │ ├── crypt │ └── sha256.c │ ├── ctype.c │ ├── err.c │ ├── grp.c │ ├── hashmap.c │ ├── io │ └── mm_io.c │ ├── libc_start.c │ ├── libgen.c │ ├── list.c │ ├── math.c │ ├── ndtree.c │ ├── pwd.c │ ├── readline.c │ ├── sched.c │ ├── setenv.c │ ├── shadow.c │ ├── stdio.c │ ├── stdlib.c │ ├── strerror.c │ ├── string.c │ ├── sys │ ├── errno.c │ ├── ioctl.c │ ├── ipc.c │ ├── mman.c │ ├── unistd.c │ └── utsname.c │ ├── syslog.c │ ├── termios.c │ ├── time.c │ ├── unistd │ ├── chdir.c │ ├── chmod.c │ ├── chown.c │ ├── close.c │ ├── creat.c │ ├── dup.c │ ├── exec.c │ ├── exit.c │ ├── fcntl.c │ ├── fork.c │ ├── getcwd.c │ ├── getdents.c │ ├── getgid.c │ ├── getpgid.c │ ├── getpid.c │ ├── getppid.c │ ├── getsid.c │ ├── getuid.c │ ├── interval.c │ ├── kill.c │ ├── lseek.c │ ├── mkdir.c │ ├── nice.c │ ├── open.c │ ├── pipe.c │ ├── read.c │ ├── readlink.c │ ├── reboot.c │ ├── rmdir.c │ ├── setgid.c │ ├── setpgid.c │ ├── setsid.c │ ├── setuid.c │ ├── signal.c │ ├── stat.c │ ├── symlink.c │ ├── unlink.c │ ├── waitpid.c │ └── write.c │ ├── vscanf.c │ └── vsprintf.c ├── mentos ├── CMakeLists.txt ├── boot.lds ├── inc │ ├── boot.h │ ├── descriptor_tables │ │ ├── gdt.h │ │ ├── idt.h │ │ ├── isr.h │ │ └── tss.h │ ├── devices │ │ ├── fpu.h │ │ └── pci.h │ ├── drivers │ │ ├── ata │ │ │ ├── ata.h │ │ │ └── ata_types.h │ │ ├── fdc.h │ │ ├── keyboard │ │ │ ├── keyboard.h │ │ │ └── keymap.h │ │ ├── mem.h │ │ ├── mouse.h │ │ ├── ps2.h │ │ └── rtc.h │ ├── elf │ │ └── elf.h │ ├── fs │ │ ├── attr.h │ │ ├── ext2.h │ │ ├── namei.h │ │ ├── pipe.h │ │ ├── procfs.h │ │ ├── vfs.h │ │ └── vfs_types.h │ ├── hardware │ │ ├── cpuid.h │ │ ├── pic8259.h │ │ └── timer.h │ ├── io │ │ ├── debug.h │ │ ├── proc_modules.h │ │ ├── vga │ │ │ ├── vga.h │ │ │ ├── vga_font.h │ │ │ ├── vga_mode.h │ │ │ └── vga_palette.h │ │ └── video.h │ ├── ipc │ │ └── ipc.h │ ├── kernel.h │ ├── klib │ │ ├── compiler.h │ │ ├── irqflags.h │ │ ├── mutex.h │ │ ├── rbtree.h │ │ ├── spinlock.h │ │ ├── stack_helper.h │ │ └── stdatomic.h │ ├── link_access.h │ ├── mem │ │ ├── alloc │ │ │ ├── buddy_system.h │ │ │ ├── slab.h │ │ │ └── zone_allocator.h │ │ ├── gfp.h │ │ ├── mm │ │ │ ├── mm.h │ │ │ ├── page.h │ │ │ ├── vm_area.h │ │ │ └── vmem.h │ │ ├── page_fault.h │ │ └── paging.h │ ├── multiboot.h │ ├── proc_access.h │ ├── process │ │ ├── pid_manager.h │ │ ├── prio.h │ │ ├── process.h │ │ ├── scheduler.h │ │ ├── scheduler_feedback.h │ │ └── wait.h │ ├── resource_tracing.h │ ├── sys │ │ └── module.h │ ├── system │ │ ├── panic.h │ │ ├── printk.h │ │ ├── signal.h │ │ └── syscall.h │ └── version.h ├── kernel.lds └── src │ ├── boot.S │ ├── boot.c │ ├── crypt │ └── sha256.c │ ├── descriptor_tables │ ├── exception.S │ ├── exception.c │ ├── gdt.S │ ├── gdt.c │ ├── idt.S │ ├── idt.c │ ├── interrupt.S │ ├── interrupt.c │ ├── tss.S │ └── tss.c │ ├── devices │ ├── fpu.c │ └── pci.c │ ├── drivers │ ├── ata.c │ ├── fdc.c │ ├── keyboard │ │ ├── keyboard.c │ │ └── keymap.c │ ├── mem.c │ ├── mouse.c │ ├── ps2.c │ └── rtc.c │ ├── elf │ └── elf.c │ ├── fs │ ├── attr.c │ ├── ext2.c │ ├── fcntl.c │ ├── ioctl.c │ ├── namei.c │ ├── open.c │ ├── pipe.c │ ├── procfs.c │ ├── read_write.c │ ├── readdir.c │ ├── stat.c │ └── vfs.c │ ├── hardware │ ├── cpuid.c │ ├── pic8259.c │ └── timer.c │ ├── io │ ├── debug.c │ ├── mm_io.c │ ├── proc_feedback.c │ ├── proc_ipc.c │ ├── proc_running.c │ ├── proc_system.c │ ├── proc_video.c │ ├── stdio.c │ ├── vga │ │ └── vga.c │ └── video.c │ ├── ipc │ ├── ipc.c │ ├── msg.c │ ├── sem.c │ └── shm.c │ ├── kernel.c │ ├── kernel │ └── sys.c │ ├── klib │ ├── assert.c │ ├── ctype.c │ ├── hashmap.c │ ├── libgen.c │ ├── list.c │ ├── math.c │ ├── mutex.c │ ├── ndtree.c │ ├── rbtree.c │ ├── spinlock.c │ ├── stdlib.c │ ├── strerror.c │ ├── string.c │ ├── time.c │ ├── vscanf.c │ └── vsprintf.c │ ├── mem │ ├── alloc │ │ ├── buddy_system.c │ │ ├── heap.c │ │ ├── slab.c │ │ └── zone_allocator.c │ ├── mm │ │ ├── mm.c │ │ ├── page.c │ │ ├── vm_area.c │ │ └── vmem.c │ ├── page_fault.c │ └── paging.c │ ├── multiboot.c │ ├── process │ ├── pid_manager.c │ ├── process.c │ ├── scheduler.c │ ├── scheduler_algorithm.c │ ├── scheduler_feedback.c │ ├── user.S │ └── wait.c │ ├── resource_tracing.c │ ├── sys │ ├── module.c │ └── utsname.c │ └── system │ ├── errno.c │ ├── panic.c │ ├── printk.c │ ├── signal.c │ └── syscall.c ├── programs ├── CMakeLists.txt ├── cat.c ├── chmod.c ├── chown.c ├── clear.c ├── cp.c ├── cpuid.c ├── date.c ├── echo.c ├── edit.c ├── env.c ├── false.c ├── head.c ├── id.c ├── init.c ├── ipcrm.c ├── ipcs.c ├── kill.c ├── login.c ├── logo.c ├── ls.c ├── man.c ├── mkdir.c ├── more.c ├── nice.c ├── poweroff.c ├── ps.c ├── pwd.c ├── rm.c ├── rmdir.c ├── runtests.c ├── shell.c ├── showpid.c ├── sleep.c ├── stat.c ├── tests │ ├── CMakeLists.txt │ ├── t_abort.c │ ├── t_alarm.c │ ├── t_big_write.c │ ├── t_chdir.c │ ├── t_creat.c │ ├── t_dup.c │ ├── t_environ.c │ ├── t_exec.c │ ├── t_exit.c │ ├── t_fork.c │ ├── t_gid.c │ ├── t_groups.c │ ├── t_grp.c │ ├── t_hashmap.c │ ├── t_itimer.c │ ├── t_kill.c │ ├── t_list.c │ ├── t_mem.c │ ├── t_mkdir.c │ ├── t_msgget.c │ ├── t_ndtree.c │ ├── t_periodic1.c │ ├── t_periodic2.c │ ├── t_periodic3.c │ ├── t_pipe_blocking.c │ ├── t_pipe_non_blocking.c │ ├── t_pwd.c │ ├── t_scanf.c │ ├── t_schedfb.c │ ├── t_semflg.c │ ├── t_semget.c │ ├── t_semop.c │ ├── t_shm.c │ ├── t_shmget.c │ ├── t_sigaction.c │ ├── t_sigfpe.c │ ├── t_siginfo.c │ ├── t_sigmask.c │ ├── t_sigusr.c │ ├── t_sleep.c │ ├── t_spwd.c │ ├── t_stopcont.c │ ├── t_syslog.c │ ├── t_time.c │ └── t_write_read.c ├── touch.c ├── uname.c └── uptime.c └── scripts └── tapview /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation 2 | 3 | # Trigger the workflow on push or pull requests for main and develop branches 4 | on: 5 | push: 6 | branches: 7 | - main 8 | - develop 9 | paths: 10 | - '**/*.c' 11 | - '**/*.cpp' 12 | - '**/*.h' 13 | - '**/*.hpp' 14 | - '**/CMakeLists.txt' 15 | - '**/Makefile' 16 | - '**/cmake/**' 17 | - '.github/workflows/documentation.yml' 18 | pull_request: 19 | branches: 20 | - main 21 | - develop 22 | paths: 23 | - '**/*.c' 24 | - '**/*.cpp' 25 | - '**/*.h' 26 | - '**/*.hpp' 27 | - '**/CMakeLists.txt' 28 | - '**/Makefile' 29 | - '**/cmake/**' 30 | - '.github/workflows/documentation.yml' 31 | 32 | jobs: 33 | doxygen: 34 | name: Generate Doxygen Documentation 35 | runs-on: ubuntu-latest 36 | 37 | steps: 38 | # Step 1: Checkout repository 39 | - name: Checkout Repository 40 | uses: actions/checkout@v4 41 | 42 | # Step 2: Install Doxygen (and optional dependencies) 43 | - name: Install Doxygen 44 | run: | 45 | sudo apt-get update 46 | sudo apt-get install -y doxygen graphviz nasm 47 | 48 | # Step 3: Configure and Build Documentation 49 | - name: Generate Documentation 50 | run: | 51 | cmake -B build -DDOXYGEN_WARN_AS_ERROR=YES 52 | cmake --build build --target mentos_documentation 53 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "gdb", 5 | "request": "attach", 6 | "name": "(gdb) Attach", 7 | "target": "localhost:1234", 8 | "remote": true, 9 | "cwd": "${workspaceRoot}/build", 10 | "valuesFormatting": "parseText" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "*.h": "c", 5 | "*.tcc": "c" 6 | } 7 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014-2024 MentOs-Team. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | -------------------------------------------------------------------------------- /files/README.md: -------------------------------------------------------------------------------- 1 | # MentOS 0.7.2 2 | 3 | Welcome to the MentOS, the Mentoring Operating System. 4 | 5 | If you want some help enter the "man" command into the cli. 6 | 7 | Bye, 8 | The Ment(OS) Team 9 | -------------------------------------------------------------------------------- /files/etc/group: -------------------------------------------------------------------------------- 1 | root:x:0:user,root,marco 2 | user:x:1000:banana,marco 3 | -------------------------------------------------------------------------------- /files/etc/hostname: -------------------------------------------------------------------------------- 1 | avalon -------------------------------------------------------------------------------- /files/etc/issue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentos-team/MentOS/bef7c4d4e04fb4fa128458a969eca8894de82f25/files/etc/issue -------------------------------------------------------------------------------- /files/etc/motd: -------------------------------------------------------------------------------- 1 | Call `man` to have a list of all the commands. -------------------------------------------------------------------------------- /files/etc/passwd: -------------------------------------------------------------------------------- 1 | root:x:0:0:Root User:/root:/bin/shell 2 | user:x:1000:1000:Normal User:/home/user:/bin/shell 3 | -------------------------------------------------------------------------------- /files/etc/shadow: -------------------------------------------------------------------------------- 1 | root:33ba1bde6222ff5836cfe0123c71e594238e675a5a5b6fbfd2ad69ae7d580a40::::::: 2 | user:35047cb1b06dabc31ce3f11b3cd0f83f7c2ed4d52851e62585906d44775a70a6::::::: 3 | -------------------------------------------------------------------------------- /files/home/user/.shellrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentos-team/MentOS/bef7c4d4e04fb4fa128458a969eca8894de82f25/files/home/user/.shellrc -------------------------------------------------------------------------------- /files/home/user/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /files/home/user/root: -------------------------------------------------------------------------------- 1 | ../../root -------------------------------------------------------------------------------- /files/home/user/tmp.md: -------------------------------------------------------------------------------- 1 | ../user/welcome.md -------------------------------------------------------------------------------- /files/home/user/welcome.md: -------------------------------------------------------------------------------- 1 | MentOS 0.7.2 2 | 3 | Welcome to the MentOS, the Mentoring Operating System. 4 | 5 | If you want some help enter the "man" command into the cli. 6 | 7 | Bye, 8 | The Ment(OS) Team 9 | -------------------------------------------------------------------------------- /files/root/.bashrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mentos-team/MentOS/bef7c4d4e04fb4fa128458a969eca8894de82f25/files/root/.bashrc -------------------------------------------------------------------------------- /files/usr/share/man/cat.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | cat [FILE]... 3 | 4 | DESCRIPTION 5 | Print the content of each given file. 6 | 7 | OPTIONS 8 | -h, --help shows command help. 9 | -------------------------------------------------------------------------------- /files/usr/share/man/cd.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | cd [DIRECTORY] 3 | 4 | DESCRIPTION 5 | cd is a command built into the shell, that changes the current working directory. 6 | 7 | If DIRECTORY is given, it will become the new directory. 8 | If no parameter is given, the HOME environment variable will be used. 9 | 10 | EXAMPLES 11 | cd 12 | # changes the working directory to your home directory. 13 | 14 | cd .. 15 | # changes the working directory to its parent directory. 16 | 17 | cd /usr/src/mentos 18 | # changes the working directory to /usr/src/mentos 19 | -------------------------------------------------------------------------------- /files/usr/share/man/chmod.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | chmod MODE FILE 3 | 4 | DESCRIPTION 5 | chmod changes the file mode bits of the given file according to mode, which 6 | must be an octal number representing the bit pattern for the new mode bits. 7 | 8 | The numeric mode is from one to four octal digits (0-7), derived by adding 9 | up the bits with values 4, 2, and 1. Omitted digits are assumed to be 10 | leading zeros. The first digit selects the set user ID (4) and set group 11 | ID (2) and restricted deletion or sticky (1) attributes. The second digit 12 | selects permissions for the user who owns the file: read (4), write (2), 13 | and execute (1); the third selects permissions for other users in the file's 14 | group, with the same values; and the fourth for other users not in the 15 | file's group, with the same values. 16 | 17 | chmod never changes the permissions of symbolic links; the chmod system call 18 | cannot change their permissions. 19 | 20 | EXAMPLES 21 | chmod 555 executable 22 | Changes the mode bits of executable to r-xr-xr-x. 23 | -------------------------------------------------------------------------------- /files/usr/share/man/chown.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | chown [OWNER][:[GROUP]] FILE 3 | 4 | DESCRIPTION 5 | chown changes the user and/or group ownership of the given file. 6 | If only a owner is given the file's group is not changed. If the owner 7 | is followed by a colon and a group name (or numeric group ID), the group 8 | ownership is changed as well. If the colon and group are given, but the 9 | owner is omitted, only the group of the file is changed. 10 | 11 | chown never changes the ownership of symbolic links; the chown system call 12 | cannot change their ownership. 13 | 14 | EXAMPLES 15 | chown root /u 16 | Change the owner of /u to "root". 17 | 18 | chown root:staff /u 19 | Likewise, but also change its group to "staff". 20 | -------------------------------------------------------------------------------- /files/usr/share/man/clear.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | clear 3 | 4 | DESCRIPTION 5 | Clears the screen. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/cp.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | cp SOURCE DEST 3 | 4 | DESCRIPTION 5 | Copy SOURCE to DEST. 6 | 7 | OPTIONS 8 | -h, --help shows command help. 9 | -------------------------------------------------------------------------------- /files/usr/share/man/cpuid.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | cpuid 3 | 4 | DESCRIPTION 5 | Not currently implemented. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/date.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | date 3 | 4 | DESCRIPTION 5 | Shows the current date. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/echo.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | echo [OPTIONS] [STRING] 3 | 4 | DESCRIPTION 5 | echo displays a line of text. 6 | 7 | The following options are available: 8 | 9 | -n Do not output a newline. 10 | -e Enable interpretation of backslash escapes. 11 | 12 | If -e is in effect, the following sequences are recognized: 13 | 14 | \n new line 15 | -------------------------------------------------------------------------------- /files/usr/share/man/env.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | env 3 | 4 | DESCRIPTION 5 | Print the current environment, with one name=value pair per line. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/false.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | false 3 | 4 | DESCRIPTION 5 | false sets the exit status to 1. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/head.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | head [-NUM] [FILE]... 3 | 4 | DESCRIPTION 5 | Output the first part of each FILE. 6 | 7 | Print the first 10 lines of each FILE to standard output. 8 | With more than one FILE, precede each with a header giving the file name. 9 | 10 | With no FILE read standard input. 11 | 12 | OPTIONS 13 | -h, --help shows command help. 14 | -NUM print only the first NUM lines. 15 | -------------------------------------------------------------------------------- /files/usr/share/man/hier.man: -------------------------------------------------------------------------------- 1 | NAME 2 | hier - description of the filesystem hierarchy 3 | 4 | DESCRIPTION 5 | The filesystem is structured like a typical Linux system and more or less 6 | resembles the Filesystem Hierarchy Standard by the Linux Foundation. 7 | 8 | The filesystem has among others the following directories: 9 | 10 | / This is the root directory. This is where the whole tree starts. 11 | 12 | /bin This directory contains basic and required executable programs. 13 | 14 | /dev Special or device files, which refer to physical devices. 15 | 16 | /etc Contains system-wide configuration files of the machine. 17 | 18 | /home Contains the home directories for individual users. 19 | 20 | /proc This is the mount point for the proc filesystem, which provides 21 | information about running processes and the kernel. 22 | 23 | /root This directory is the home directory for the root user. 24 | 25 | /usr/bin 26 | This is the directory for additional executable programs. 27 | 28 | /usr/srv 29 | Contains the source code used to build the system. 30 | 31 | /usr/share 32 | Contains subdirectories with specific application data, that can be shared 33 | among different architectures of the same OS. 34 | 35 | /usr/share/man 36 | Manual pages go here. 37 | 38 | /var Contains files which may change in size. 39 | 40 | /var/lib 41 | Variable state information for programs. 42 | -------------------------------------------------------------------------------- /files/usr/share/man/id.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | id [OPTIONS] 3 | 4 | DESCRIPTION 5 | Print user and group information for the current process. 6 | 7 | The following options are available: 8 | 9 | -g, --group 10 | print only the effective group ID 11 | 12 | -u, --user 13 | print only the effective user ID 14 | 15 | --help display a help message and exit 16 | -------------------------------------------------------------------------------- /files/usr/share/man/init.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | init 3 | 4 | DESCRIPTION 5 | init is used as PID 1 program, started by the operating system's kernel. 6 | 7 | init forks and executes the login program in the new process. 8 | It then awaits child processes. If the forked login process terminates 9 | a new one will be started. 10 | -------------------------------------------------------------------------------- /files/usr/share/man/ipcs.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | ipcs [options] 3 | 4 | DESCRIPTION 5 | Ipcs shows information on System V inter-process communication facilities. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/kill.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | kill SIGNAL PID... 3 | kill PID 4 | kill -l 5 | 6 | DESCRIPTION 7 | The kill utility shall send a signal to the process or processes specified 8 | by each PID operand. 9 | 10 | If no signal is given the TERM signal will be send to the process specified 11 | by PID. 12 | 13 | OPTIONS 14 | -l Write a list of all suported signals. 15 | -------------------------------------------------------------------------------- /files/usr/share/man/login.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | login 3 | 4 | DESCRIPTION 5 | login is used when signing onto a system. 6 | 7 | login prompts for the username and the password, where appropriate. 8 | Echoing is disabled to prevent revealing the password. 9 | 10 | The user and group ID will be set according to their values in the 11 | /etc/passwd file. 12 | 13 | The greeting message from the file /etc/motd is printed and the 14 | user shell specified in /etc/passwd is started. 15 | -------------------------------------------------------------------------------- /files/usr/share/man/ls.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | ls [OPTIONS] [DIRECTORY]... 3 | 4 | DESCRIPTION 5 | List information about the given file, or the files contained in the given 6 | folder. If not argument is provided it will list information about files 7 | inside the current folder. 8 | 9 | OPTIONS 10 | -h, --help shows command help. 11 | -a, --all list all entries. 12 | -l, --long show the entries as a detailed long list. 13 | -i, --inode print the index number of each file 14 | -1 list one file per line 15 | -------------------------------------------------------------------------------- /files/usr/share/man/man.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | man [PAGE] 3 | 4 | DESCRIPTION 5 | man is the system's manual pager. The page argument given to man is 6 | normally the name of a program or utility. 7 | 8 | Conventional section names include SYNOPSIS, CONFIGURATION, DESCRIPTION, 9 | OPTIONS, EXIT STATUS and EXAMPLE. 10 | 11 | The following conventions apply to the SYNOPSIS section and can be used as 12 | a guide in other sections. 13 | 14 | [-abc] any or all arguments within [ ] are optional. 15 | -a|-b options delimited by | cannot be used together. 16 | argument ... argument is repeatable. 17 | [expression] ... entire expression within [ ] is repeatable. 18 | -------------------------------------------------------------------------------- /files/usr/share/man/mkdir.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | mkdir DIRECTORY 3 | 4 | DESCRIPTION 5 | Create the DIRECTORY, if it does not exist. 6 | 7 | OPTIONS 8 | --help shows command help. 9 | -------------------------------------------------------------------------------- /files/usr/share/man/more.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | more [FILE] 3 | 4 | DESCRIPTION 5 | more is a filter for paging through text one screenful at a time. 6 | 7 | OPTIONS 8 | -h, --help shows command help. 9 | 10 | KEY BINDINGS 11 | q Exit from more 12 | space Display next screen size 13 | return Display next line 14 | -------------------------------------------------------------------------------- /files/usr/share/man/passwd.man: -------------------------------------------------------------------------------- 1 | NAME 2 | passwd - the password file 3 | 4 | DESCRIPTION 5 | /etc/passwd contains one line for each user account, with seven fields 6 | delimited by colons (":"). 7 | 8 | These fields are: 9 | * login name 10 | * optional encrypted password 11 | * numerical user ID 12 | * numerical group ID 13 | * user name or comment field 14 | * user home directory 15 | * optional user command interpreter 16 | 17 | If the password field is a lower-case "x", then the encrypted password is 18 | actually stored in the shadow file instead; there must be a corresponding 19 | line in the /etc/shadow file, or else the user account is invalid. 20 | 21 | The home directory field provides the name of the initial working directory. 22 | The login program uses this information to set the value of the $HOME 23 | environmental variable. 24 | 25 | The command interpreter field provides the name of the user's command 26 | language interpreter, or the name of the initial program to execute. 27 | The login program uses this information to set the value of the $SHELL 28 | environmental variable. 29 | -------------------------------------------------------------------------------- /files/usr/share/man/rmdir.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | rmdir DIRECTORY 3 | 4 | DESCRIPTION 5 | Remove the DIRECTORY, if it is empty. 6 | 7 | OPTIONS 8 | -h, --help shows command help. 9 | -------------------------------------------------------------------------------- /files/usr/share/man/shadow.man: -------------------------------------------------------------------------------- 1 | NAME 2 | shadow - shadowed password file 3 | 4 | DESCRIPTION 5 | shadow is a file which contains the password information for the 6 | system's accounts. 7 | 8 | This file must not be readable by regular users if password security is to 9 | be maintained. 10 | 11 | Each line of this file contains 9 fields, separated by colons (“:”), in the 12 | following order: 13 | 14 | * login name 15 | * encrypted password 16 | * date of last password change 17 | * minimum password age 18 | * maximum password age 19 | * password warning period 20 | * password inactivity period 21 | * account expiration date 22 | * reserved field 23 | -------------------------------------------------------------------------------- /files/usr/share/man/shell.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | shell [FILE] 3 | 4 | DESCRIPTION 5 | shell reads and executes commands from a file or from standard input. 6 | 7 | INVOCATION 8 | An interactive shell is one started without arguments, whose standard 9 | input and error are both connected to terminals. 10 | 11 | When shell is started as interactive shell it first reads and executes 12 | commands from the file ~/.shellrc. 13 | -------------------------------------------------------------------------------- /files/usr/share/man/showpid.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | showpid 3 | 4 | DESCRIPTION 5 | showpid uses getppid() to print the ID of the parent process. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/sleep.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | sleep NUMBER 3 | 4 | DESCRIPTION 5 | Pause for NUMBER seconds. 6 | -------------------------------------------------------------------------------- /files/usr/share/man/stat.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | stat [OPTIONS]... FILE... 3 | 4 | DESCRIPTION 5 | Display file status of one or more given files. 6 | 7 | OPTIONS 8 | -h, --help shows command help. 9 | 10 | EXIT STATUS 11 | stat will exit with status 1 if the stat system call fails. 12 | Otherwise, stat will exit with status 0. 13 | -------------------------------------------------------------------------------- /files/usr/share/man/touch.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | touch FILE 3 | 4 | DESCRIPTION 5 | The touch utility shall change the last data modification timestamps, 6 | the last data access timestamps, or both. 7 | 8 | touch shall perform actions equivalent to the following functions: 9 | 1. If file does not exist: 10 | 11 | a. The creat() function is called with the following arguments: 12 | -- The file operand is used as the path argument. 13 | -- The value of the bitwise-inclusive OR of S_IRUSR, S_IWUSR, 14 | S_IRGRP, S_IROTH is used as the mode argument. 15 | b. The file is opened for reading. 16 | 17 | OPTIONS 18 | -h, --help shows command help. 19 | -------------------------------------------------------------------------------- /files/usr/share/man/uname.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | uname [-a|-r|-i] 3 | 4 | DESCRIPTION 5 | Uname prints kernel and system information. 6 | 7 | The following options are available: 8 | 9 | -a, --all 10 | Print kernel version and processor type 11 | 12 | -r, --rev 13 | Print only the kernel version 14 | 15 | -i, --info 16 | Print all info of system and kernel 17 | 18 | -h, --help 19 | Display a help message and exit 20 | -------------------------------------------------------------------------------- /files/usr/share/man/uptime.man: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | uptime 3 | 4 | DESCRIPTION 5 | Tell how long the system has been running. 6 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | set timeout=5 2 | set default=0 3 | 4 | menuentry "MentOS" { 5 | multiboot /boot/bootloader.bin 6 | boot 7 | } 8 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg.runtests: -------------------------------------------------------------------------------- 1 | set timeout=0 2 | set default=0 3 | 4 | menuentry "MentOS tests" { 5 | multiboot /boot/bootloader.bin runtests 6 | boot 7 | } 8 | -------------------------------------------------------------------------------- /libc/inc/assert.h: -------------------------------------------------------------------------------- 1 | /// @file assert.h 2 | /// @brief Defines the function and pre-processor macro for assertions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "os_root_path.h" 9 | 10 | /// @brief Function used to log the information of a failed assertion. 11 | /// @param assertion The failed assertion. 12 | /// @param file The file where the assertion is located. 13 | /// @param function The function where the assertion is. 14 | /// @param line The line inside the file. 15 | void __assert_fail(const char *assertion, const char *file, const char *function, unsigned int line); 16 | 17 | /// @brief Assert function. 18 | #define assert(expression) ((expression) ? (void)0 : __assert_fail(#expression, __RELATIVE_PATH__, __func__, __LINE__)) 19 | -------------------------------------------------------------------------------- /libc/inc/bits/ioctls.h: -------------------------------------------------------------------------------- 1 | /// @file ioctls.h 2 | /// @brief Input/Output ConTroL (IOCTL) numbers. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #define TCGETS 0x5401U ///< Get the current serial port settings. 9 | #define TCSETS 0x5402U ///< Set the current serial port settings. 10 | -------------------------------------------------------------------------------- /libc/inc/bits/stat.h: -------------------------------------------------------------------------------- 1 | /// @file stat.h 2 | /// @brief Defines the structure used by the functiosn fstat(), lstat(), and stat(). 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #if !defined(__SYS_STAT_H) && !defined(__KERNEL__) 9 | #error "Never include directly; use instead." 10 | #endif 11 | 12 | #include "stddef.h" 13 | #include "sys/types.h" 14 | #include "time.h" 15 | 16 | /// @brief Data structure which contains information about a file. 17 | typedef struct stat { 18 | /// ID of device containing file. 19 | dev_t st_dev; 20 | /// File serial number. 21 | ino_t st_ino; 22 | /// Mode of file (file type and permissions). 23 | mode_t st_mode; 24 | /// Number of hard links to the file. 25 | nlink_t st_nlink; 26 | /// File user ID. 27 | uid_t st_uid; 28 | /// File group ID. 29 | gid_t st_gid; 30 | /// Device ID (if special file). 31 | dev_t st_rdev; 32 | /// File size in bytes. 33 | off_t st_size; 34 | /// Preferred block size for filesystem I/O. 35 | blksize_t st_blksize; 36 | /// Number of blocks allocated for the file. 37 | blkcnt_t st_blocks; 38 | /// Time of last access. 39 | time_t st_atime; 40 | /// Time of last data modification. 41 | time_t st_mtime; 42 | /// Time of last status change. 43 | time_t st_ctime; 44 | } stat_t; 45 | -------------------------------------------------------------------------------- /libc/inc/bits/termios-struct.h: -------------------------------------------------------------------------------- 1 | /// @file termios-struct.h 2 | /// @brief Definition of the `termios` structure. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// Type for control characters. 9 | typedef unsigned char cc_t; 10 | /// Type for speed. 11 | typedef unsigned int speed_t; 12 | /// Type for flags. 13 | typedef unsigned int tcflag_t; 14 | /// The number of control characters. 15 | #define NCCS 32 16 | 17 | /// @brief Stores information about a terminal IOs. 18 | typedef struct termios { 19 | tcflag_t c_iflag; ///< input mode flags 20 | tcflag_t c_oflag; ///< output mode flags 21 | tcflag_t c_cflag; ///< control mode flags 22 | tcflag_t c_lflag; ///< local mode flags 23 | cc_t c_line; ///< line discipline 24 | cc_t c_cc[NCCS]; ///< control characters 25 | speed_t c_ispeed; ///< input speed 26 | speed_t c_ospeed; ///< output speed 27 | } termios_t; 28 | 29 | //These flags generally control higher-level aspects of input processing than 30 | // the input modes flags described in Input Modes, such as echoing, signals, and 31 | // the choice of canonical or noncanonical input. 32 | 33 | #define ISIG 0x00000080 ///< Controls whether the INTR, QUIT, and SUSP characters are recognized. 34 | #define ICANON 0x00000100 ///< Enables canonical input processing mode. 35 | #define ECHO 0x00000008 ///< Echo input characters. 36 | #define ECHOE 0x00000002 ///< If ICANON is set, the ERASE character erases the preceding character. 37 | #define ECHOK 0x00000004 ///< If ICANON is set, the KILL character erases the current line. 38 | #define ECHONL 0x00000010 ///< If ICANON is set, echo the NL character even if ECHO is not set. 39 | #define NOFLSH 0x80000000 ///< Do not clear in/out queues when receiving INTR, QUIT, and SUSP. 40 | #define TOSTOP 0x00400000 ///< Allows SIGTTOU signals generated by background processes. 41 | #define ECHOCTL 0x00000040 ///< If this and ECHO are set, control characters with ‘^’ are echoed. 42 | #define ECHOKE 0x00000001 ///< If ICANON is set, KILL is echoed by erasing each character on the line. 43 | #define IEXTEN 0x00000400 ///< Enables implementation-defined input processing. 44 | 45 | /// @brief Mask for extracting control values. 46 | #define CTRL(x) ((x) & 037) 47 | -------------------------------------------------------------------------------- /libc/inc/ctype.h: -------------------------------------------------------------------------------- 1 | /// @file ctype.h 2 | /// @brief Functions related to character handling. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Check if the given value is a digit. 9 | /// @param c The input character. 10 | /// @return 1 on success, 0 otherwise. 11 | int isdigit(int c); 12 | 13 | /// @brief Check if the given value is a letter. 14 | /// @param c The input character. 15 | /// @return 1 on success, 0 otherwise. 16 | int isalpha(int c); 17 | 18 | /// @brief Check if the given value is a control character. 19 | /// @param c The input character. 20 | /// @return 1 on success, 0 otherwise. 21 | int iscntrl(int c); 22 | 23 | /// @brief Check if the given value is either a letter or a digit. 24 | /// @param c The input character. 25 | /// @return 1 on success, 0 otherwise. 26 | int isalnum(int c); 27 | 28 | /// @brief Check if the given value is an hexadecimal digit. 29 | /// @param c The input character. 30 | /// @return 1 on success, 0 otherwise. 31 | int isxdigit(int c); 32 | 33 | /// @brief Check if the given value is a lower case letter. 34 | /// @param c The input character. 35 | /// @return 1 on success, 0 otherwise. 36 | int islower(int c); 37 | 38 | /// @brief Check if the given value is an upper case letter. 39 | /// @param c The input character. 40 | /// @return 1 on success, 0 otherwise. 41 | int isupper(int c); 42 | 43 | /// @brief Transforms the given value into a lower case letter. 44 | /// @param c The input letter. 45 | /// @return The input letter turned into a lower case letter. 46 | int tolower(int c); 47 | 48 | /// @brief Transforms the given value into an upper case letter. 49 | /// @param c The input letter. 50 | /// @return The input letter turned into an upper case letter. 51 | int toupper(int c); 52 | 53 | /// @brief Check if the given value is a whitespace. 54 | /// @param c The input character. 55 | /// @return 1 on success, 0 otherwise. 56 | int isspace(int c); 57 | -------------------------------------------------------------------------------- /libc/inc/dirent.h: -------------------------------------------------------------------------------- 1 | /// @file dirent.h 2 | /// @brief Functions used to manage directories. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "limits.h" 9 | #include "stddef.h" 10 | 11 | /// File types for `d_type'. 12 | enum { 13 | DT_UNKNOWN = 0, 14 | DT_FIFO = 1, 15 | DT_CHR = 2, 16 | DT_DIR = 4, 17 | DT_BLK = 6, 18 | DT_REG = 8, 19 | DT_LNK = 10, 20 | DT_SOCK = 12, 21 | DT_WHT = 14 22 | }; 23 | 24 | /// @brief Characters describing the direactory entry. 25 | static const char dt_char_array[] = { 26 | '?', // DT_UNKNOWN = 0, 27 | 'p', // DT_FIFO = 1, 28 | 'c', // DT_CHR = 2, 29 | '*', 30 | 'd', // DT_DIR = 4, 31 | '*', 32 | 'b', // DT_BLK = 6, 33 | '*', 34 | '-', // DT_REG = 8, 35 | '*', 36 | 'l', // DT_LNK = 10, 37 | '*', 38 | 's', // DT_SOCK = 12, 39 | '*', 40 | '?', // DT_WHT = 14 41 | }; 42 | 43 | /// Directory entry. 44 | typedef struct dirent { 45 | ino_t d_ino; ///< Inode number. 46 | off_t d_off; ///< Offset to next linux_dirent. 47 | unsigned short d_reclen; ///< Length of this linux_dirent. 48 | unsigned short d_type; ///< type of the directory entry. 49 | char d_name[NAME_MAX]; ///< Filename (null-terminated) 50 | } dirent_t; 51 | 52 | /// Provide access to the directory entries. 53 | /// @param fd The fd pointing to the opened directory. 54 | /// @param dirp The buffer where de data should be placed. 55 | /// @param count The size of the buffer. 56 | /// @return On success, the number of bytes read is returned. On end of 57 | /// directory, 0 is returned. On error, -1 is returned, and errno is set 58 | /// appropriately. 59 | ssize_t getdents(int fd, dirent_t *dirp, unsigned int count); 60 | -------------------------------------------------------------------------------- /libc/inc/io/mm_io.h: -------------------------------------------------------------------------------- 1 | /// @file mm_io.h 2 | /// @brief Memory Mapped IO functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "stdint.h" 9 | 10 | /// @brief Reads a 8-bit value from the given address. 11 | /// @param addr the address we want to read from. 12 | /// @return the value we read. 13 | uint8_t in_memb(uint32_t addr); 14 | 15 | /// @brief Reads a 16-bit value from the given address. 16 | /// @param addr the address we want to read from. 17 | /// @return the value we read. 18 | uint16_t in_mems(uint32_t addr); 19 | 20 | /// @brief Reads a 32-bit value from the given address. 21 | /// @param addr the address we want to read from. 22 | /// @return the value we read. 23 | uint32_t in_meml(uint32_t addr); 24 | 25 | /// @brief Writes a 8-bit value at the given address. 26 | /// @param addr the address we want to write to. 27 | /// @param value the value we want to write. 28 | void out_memb(uint32_t addr, uint8_t value); 29 | 30 | /// @brief Writes a 16-bit value at the given address. 31 | /// @param addr the address we want to write to. 32 | /// @param value the value we want to write. 33 | void out_mems(uint32_t addr, uint16_t value); 34 | 35 | /// @brief Writes a 32-bit value at the given address. 36 | /// @param addr the address we want to write to. 37 | /// @param value the value we want to write. 38 | void out_meml(uint32_t addr, uint32_t value); 39 | -------------------------------------------------------------------------------- /libc/inc/libgen.h: -------------------------------------------------------------------------------- 1 | /// @file libgen.h 2 | /// @brief String routines. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "stddef.h" 7 | 8 | /// @brief Extracts the parent directory of the given path and saves it inside 9 | /// the given buffer, e.g., from "/home/user/test.txt" it extracts "/home/user". 10 | /// If the path does not contain a '/', it will return ".". 11 | /// @param path the path we are parsing. 12 | /// @param buffer the buffer where we save the directory name. 13 | /// @param buflen the length of the buffer. 14 | /// @return 1 if succesfull, or 0 if the buffer cannot contain the path. 15 | int dirname(const char *path, char *buffer, size_t buflen); 16 | 17 | /// @brief Extract the component after the final '/'. 18 | /// @param path the path from which we extract the final component. 19 | /// @return a pointer after the final '/', or path itself it none was found. 20 | const char *basename(const char *path); 21 | 22 | /// @brief Return the canonicalized absolute pathname. 23 | /// @param path the path we are canonicalizing. 24 | /// @param buffer where we will store the canonicalized path. 25 | /// @param buflen the size of the buffer. 26 | /// @return If there is no error, realpath() returns a pointer to the buffer. 27 | /// Otherwise, it returns NULL, the contents of the array buffer are undefined, 28 | /// and errno is set to indicate the error. 29 | char *realpath(const char *path, char *buffer, size_t buflen); 30 | -------------------------------------------------------------------------------- /libc/inc/limits.h: -------------------------------------------------------------------------------- 1 | /// @file limits.h 2 | /// @brief OS numeric limits. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// Number of bits in a `char`. 9 | #define CHAR_BIT 8 10 | 11 | /// Minimum value a `signed char` can hold. 12 | #define SCHAR_MIN (-128) 13 | 14 | /// Maximum value a `signed char` can hold. 15 | #define SCHAR_MAX 127 16 | 17 | /// Minimum value a `char` can hold (assuming signed by default). 18 | #define CHAR_MIN SCHAR_MIN 19 | 20 | /// Maximum value a `char` can hold. 21 | #define CHAR_MAX SCHAR_MAX 22 | 23 | /// Maximum value an `unsigned char` can hold. 24 | #define UCHAR_MAX 255 25 | 26 | /// Maximum value a `signed short int` can hold. 27 | #define SHRT_MAX 32767 28 | 29 | /// Minimum value a `signed short int` can hold. 30 | #define SHRT_MIN (-SHRT_MAX - 1) 31 | 32 | /// Maximum value an `unsigned short int` can hold. 33 | #define USHRT_MAX 65535 34 | 35 | /// Maximum value a `signed int` can hold. 36 | #define INT_MAX 2147483647 37 | 38 | /// Minimum value a `signed int` can hold. 39 | #define INT_MIN (-INT_MAX - 1) 40 | 41 | /// Maximum value an `unsigned int` can hold. 42 | #define UINT_MAX 4294967295U 43 | 44 | /// Maximum value a `signed long int` can hold (assuming 32-bit long). 45 | #define LONG_MAX 2147483647L 46 | 47 | /// Minimum value a `signed long int` can hold. 48 | #define LONG_MIN (-LONG_MAX - 1L) 49 | 50 | /// Maximum value an `unsigned long int` can hold. 51 | #define ULONG_MAX 4294967295UL 52 | 53 | /// Maximum number of characters in a file name. 54 | #define NAME_MAX 255 55 | 56 | /// Maximum number of characters in a path name. 57 | #define PATH_MAX 4096 58 | 59 | /// Maximum length of arguments provided to exec function. 60 | #define ARG_MAX 256 61 | 62 | /// Maximum pid number. 63 | #define PID_MAX_LIMIT 32768 64 | 65 | /// Maximum number of links to follow during resolving a path. 66 | #define SYMLOOP_MAX 8 67 | -------------------------------------------------------------------------------- /libc/inc/list_head_algorithm.h: -------------------------------------------------------------------------------- 1 | /// @file list_head_algorithm.h 2 | /// @brief Some general algorithm that might come in handy while using list_head. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "list_head.h" 9 | 10 | /// @brief list_head_t comparison function. 11 | typedef int (*list_head_compare)(const list_head_t *, const list_head_t *); 12 | 13 | /// @brief - 14 | /// @param list 15 | /// @param compare 16 | static inline void list_head_sort(list_head_t *list, list_head_compare compare) 17 | { 18 | list_head_t *current = NULL; 19 | list_head_t *index = NULL; 20 | list_head_t *next = NULL; 21 | // Check whether list is empty 22 | if (!list_head_empty(list)) { 23 | // Keeps track if we need to restart the outer loop. 24 | int restart = 0; 25 | // Current will point to head 26 | for (current = list->next; current->next != list;) { 27 | // Save pointer to next. 28 | next = current->next; 29 | // Reset restart flag. 30 | restart = 0; 31 | // Index will point to node next to current 32 | for (index = current->next; index != list; index = index->next) { 33 | // If current's data is greater than index's data, swap the data of 34 | // current and index 35 | if (compare(current, index)) { 36 | list_head_swap(index, current); 37 | restart = 1; 38 | } 39 | } 40 | // Check if we need to restart. 41 | if (restart) { 42 | current = list->next; 43 | } else { 44 | current = next; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /libc/inc/os_root_path.h: -------------------------------------------------------------------------------- 1 | /// @file os_root_path.h 2 | /// @brief Provides a macro to extract the relative path of the current file from the project root. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Extracts the relative file path by removing the `MENTOS_ROOT` prefix. 9 | /// @note If `MENTOS_ROOT` does not match the start of `__FILE__`, the full file path is returned. 10 | #ifndef __RELATIVE_PATH__ 11 | #define __RELATIVE_PATH__ \ 12 | (__builtin_strncmp(__FILE__, MENTOS_ROOT, sizeof(MENTOS_ROOT) - 1) == 0 ? (&__FILE__[sizeof(MENTOS_ROOT)]) \ 13 | : __FILE__) 14 | #endif 15 | -------------------------------------------------------------------------------- /libc/inc/readline.h: -------------------------------------------------------------------------------- 1 | /// @file readline.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "stddef.h" 7 | 8 | /// @brief Reads a line from the given file descriptor into the buffer. 9 | /// @param fd The file descriptor to read from. 10 | /// @param buffer The buffer where the read line will be stored. Must not be NULL. 11 | /// @param buflen The size of the buffer. 12 | /// @param read_len A pointer to store the length of the read line. Can be NULL if not needed. 13 | /// @return 1 if a newline was found and the line was read successfully, 14 | /// 0 if the end of the file was reached, 15 | /// -1 if no newline was found and partial data was read. 16 | int readline(int fd, char *buffer, size_t buflen, ssize_t *read_len); 17 | -------------------------------------------------------------------------------- /libc/inc/sched.h: -------------------------------------------------------------------------------- 1 | /// @file sched.h 2 | /// @brief Structures and functions for managing the scheduler. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "stdbool.h" 7 | #include "sys/types.h" 8 | #include "time.h" 9 | 10 | /// @brief Structure that describes scheduling parameters. 11 | typedef struct sched_param { 12 | /// Static execution priority. 13 | int sched_priority; 14 | /// Expected period of the task 15 | time_t period; 16 | /// Absolute deadline 17 | time_t deadline; 18 | /// Absolute time of arrival of the task 19 | time_t arrivaltime; 20 | /// Is task periodic? 21 | bool_t is_periodic; 22 | } sched_param_t; 23 | 24 | /// @brief Sets scheduling parameters. 25 | /// @param pid pid of the process we want to change the parameters. If zero, 26 | /// then the parameters of the calling process are set. 27 | /// @param param The interpretation of the argument param depends on the 28 | /// scheduling policy of the thread identified by pid. 29 | /// @return 0 on success, -1 on failure and errno is set to indicate the error. 30 | int sched_setparam(pid_t pid, const sched_param_t *param); 31 | 32 | /// @brief Gets scheduling parameters. 33 | /// @param pid pid of the process we want to retrieve the parameters. If zero, 34 | /// then the parameters of the calling process are returned. 35 | /// @param param The interpretation of the argument param depends on the 36 | /// scheduling policy of the thread identified by pid. 37 | /// @return 0 on success, -1 on failure and errno is set to indicate the error. 38 | int sched_getparam(pid_t pid, sched_param_t *param); 39 | 40 | /// @brief Placed at the end of an infinite while loop, stops the process until, 41 | /// its next period starts. The calling process must be a periodic one. 42 | /// @return 0 on success, -1 on failure and errno is set to indicate the error. 43 | int waitperiod(void); 44 | -------------------------------------------------------------------------------- /libc/inc/stdarg.h: -------------------------------------------------------------------------------- 1 | /// @file stdarg.h 2 | /// @brief Contains the macros required to manage variable number of arguments. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief The va_list type is an array containing a single element of one 9 | /// structure containing the necessary information to implement the 10 | /// va_arg macro. 11 | typedef char *va_list; 12 | 13 | /// @brief The type of the item on the stack. 14 | #define va_item int 15 | 16 | /// @brief Amount of space required in an argument list (ie. the stack) for an 17 | /// argument of type t. 18 | #define va_size(t) (((sizeof(t) + sizeof(va_item) - 1) / sizeof(va_item)) * sizeof(va_item)) 19 | 20 | /// @brief The start of a variadic list. 21 | #define va_start(ap, last_arg) ((ap) = ((va_list)(&(last_arg)) + va_size(last_arg))) 22 | 23 | /// @brief The end of a variadic list. 24 | #define va_end(ap) ((void)0) 25 | 26 | /// @brief The argument of a variadic list. 27 | #define va_arg(ap, t) ((ap) += va_size(t), *((t *)((ap) - va_size(t)))) 28 | 29 | /// @brief Copy a variadic list. 30 | #define va_copy(dest, src) ((dest) = (src)) 31 | -------------------------------------------------------------------------------- /libc/inc/stdbool.h: -------------------------------------------------------------------------------- 1 | /// @file stdbool.h 2 | /// @brief Defines the boolean values. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Define boolean value. 9 | typedef enum bool { 10 | false, ///< [0] False. 11 | true ///< [1] True. 12 | } __attribute__((__packed__)) bool_t; 13 | -------------------------------------------------------------------------------- /libc/inc/stdint.h: -------------------------------------------------------------------------------- 1 | /// @file stdint.h 2 | /// @brief Standard integer data-types. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Define the signed 64-bit integer. 9 | typedef int int64_t; 10 | 11 | /// @brief Define the unsigned 64-bit integer. 12 | typedef unsigned int uint64_t; 13 | 14 | /// @brief Define the signed 32-bit integer. 15 | typedef int int32_t; 16 | 17 | /// @brief Define the unsigned 32-bit integer. 18 | typedef unsigned int uint32_t; 19 | 20 | /// @brief Define the signed 16-bit integer. 21 | typedef short int16_t; 22 | 23 | /// @brief Define the unsigned 16-bit integer. 24 | typedef unsigned short uint16_t; 25 | 26 | /// @brief Define the signed 8-bit integer. 27 | typedef char int8_t; 28 | 29 | /// @brief Define the unsigned 8-bit integer. 30 | typedef unsigned char uint8_t; 31 | 32 | /// @brief Define the signed 32-bit pointer. 33 | typedef signed intptr_t; 34 | 35 | /// @brief Define the unsigned 32-bit pointer. 36 | typedef unsigned uintptr_t; 37 | 38 | /// @brief Minimum value of a signed 8-bit integer. 39 | #define INT8_MIN (-128) 40 | 41 | /// @brief Minimum value of a signed 16-bit integer. 42 | #define INT16_MIN (-32768) 43 | 44 | /// @brief Minimum value of a signed 32-bit integer. 45 | #define INT32_MIN (-2147483648) 46 | 47 | /// @brief Maximum value of a signed 8-bit integer. 48 | #define INT8_MAX (+127) 49 | 50 | /// @brief Maximum value of a signed 16-bit integer. 51 | #define INT16_MAX (+32767) 52 | 53 | /// @brief Maximum value of a signed 32-bit integer. 54 | #define INT32_MAX (+2147483647) 55 | 56 | /// @brief Maximum value of an unsigned 8-bit integer. 57 | #define UINT8_MAX (+255) 58 | 59 | /// @brief Maximum value of an unsigned 16-bit integer. 60 | #define UINT16_MAX (+65535) 61 | 62 | /// @brief Maximum value of an unsigned 32-bit integer. 63 | #define UINT32_MAX (+4294967295U) 64 | 65 | /// @brief Maximum value representable by size_t. 66 | #define SIZE_MAX (+4294967295U) 67 | -------------------------------------------------------------------------------- /libc/inc/strerror.h: -------------------------------------------------------------------------------- 1 | /// @file strerror.h 2 | /// @brief Contains the function that transfornms an errno into a string. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | /// @brief Returns the string representing the error number. 11 | /// @param errnum The error number. 12 | /// @return The string representing the error number. 13 | char *strerror(int errnum); 14 | -------------------------------------------------------------------------------- /libc/inc/sys/ioctl.h: -------------------------------------------------------------------------------- 1 | /// @file ioctl.h 2 | /// @brief Input/Output ConTroL (IOCTL) functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Executes a device-specific control operation on a file descriptor. 9 | /// @param fd The file descriptor for the device or file being operated on. 10 | /// @param request The `ioctl` command, defining the action or configuration. 11 | /// @param data Additional data needed for the `ioctl` command, often a pointer to user-provided data. 12 | /// @return Returns 0 on success; on error, returns a negative error code. 13 | long ioctl(int fd, unsigned int request, unsigned long data); 14 | -------------------------------------------------------------------------------- /libc/inc/sys/ipc.h: -------------------------------------------------------------------------------- 1 | /// @file ipc.h 2 | /// @brief Inter-Process Communication (IPC) structures. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "stddef.h" 9 | #include "sys/types.h" 10 | 11 | #define IPC_CREAT 01000 ///< Create key if key does not exist. 12 | #define IPC_EXCL 02000 ///< Fail if key exists. 13 | #define IPC_NOWAIT 04000 ///< Return error on wait. 14 | #define IPC_RMID 0 ///< Remove identifier. 15 | #define IPC_SET 1 ///< Set `ipc_perm' options. 16 | #define IPC_STAT 2 ///< Get `ipc_perm' options. 17 | #define IPC_INFO 3 ///< See ipcs. 18 | 19 | #define IPC_PRIVATE ((key_t)0) ///< assures getting a new ipc_key. 20 | 21 | /// @brief Permission details of an IPC object. 22 | struct ipc_perm { 23 | /// Key associated to the IPC. 24 | key_t key; 25 | /// Effective UID of owner. 26 | uid_t uid; 27 | /// Effective GID of owner. 28 | gid_t gid; 29 | /// Effective UID of creator. 30 | uid_t cuid; 31 | /// Effective GID of creator. 32 | gid_t cgid; 33 | /// Permissions. 34 | unsigned short mode; 35 | /// Sequence number. 36 | unsigned short __seq; 37 | }; 38 | 39 | /// @brief Returns a possible IPC key based upon the filepath and the id. 40 | /// @param path The file path. 41 | /// @param id the project id. 42 | /// @return the IPC key. 43 | key_t ftok(const char *path, int id); 44 | -------------------------------------------------------------------------------- /libc/inc/sys/kernel_levels.h: -------------------------------------------------------------------------------- 1 | /// @file kernel_levels.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | // Integer equivalents of KERN_ 9 | #define LOGLEVEL_DEFAULT (-1) ///< default-level messages. 10 | #define LOGLEVEL_EMERG 0 ///< system is unusable. 11 | #define LOGLEVEL_ALERT 1 ///< action must be taken immediately. 12 | #define LOGLEVEL_CRIT 2 ///< critical conditions. 13 | #define LOGLEVEL_ERR 3 ///< error conditions. 14 | #define LOGLEVEL_WARNING 4 ///< warning conditions. 15 | #define LOGLEVEL_NOTICE 5 ///< normal but significant condition. 16 | #define LOGLEVEL_INFO 6 ///< informational. 17 | #define LOGLEVEL_DEBUG 7 ///< debug-level messages. 18 | -------------------------------------------------------------------------------- /libc/inc/sys/mman.h: -------------------------------------------------------------------------------- 1 | /// @file mman.h 2 | /// @brief Functions for managing mappings in virtual address space. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "stddef.h" 9 | 10 | #define PROT_READ 0x1 ///< Page can be read. 11 | #define PROT_WRITE 0x2 ///< Page can be written. 12 | #define PROT_EXEC 0x4 ///< Page can be executed. 13 | 14 | #define MAP_SHARED 0x01 ///< The memory is shared. 15 | #define MAP_PRIVATE 0x02 ///< The memory is private. 16 | 17 | #if 0 18 | 19 | /// @brief creates a new mapping in the virtual address space of the calling process. 20 | /// @param addr the starting address for the new mapping. 21 | /// @param length specifies the length of the mapping (which must be greater than 0). 22 | /// @param prot describes the desired memory protection of the mapping (and must not conflict with the open mode of the file). 23 | /// @param flags determines whether updates to the mapping are visible to other processes mapping the same region. 24 | /// @param fd in case of file mapping, the file descriptor to use. 25 | /// @param offset offset in the file, which must be a multiple of the page size PAGE_SIZE. 26 | /// @return returns a pointer to the mapped area, -1 and errno is set. 27 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 28 | 29 | /// @brief deletes the mappings for the specified address range. 30 | /// @param addr the starting address. 31 | /// @param length the length of the mapped area. 32 | /// @return 0 on success, -1 on falure and errno is set. 33 | int munmap(void *addr, size_t length); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libc/inc/sys/reboot.h: -------------------------------------------------------------------------------- 1 | /// @file reboot.h 2 | /// @brief Defines the values required to issue a reboot. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// Magic values required to use _reboot() system call. 9 | #define LINUX_REBOOT_MAGIC1 0xfee1dead 10 | /// Magic values required to use _reboot() system call. 11 | #define LINUX_REBOOT_MAGIC2 672274793 12 | /// Magic values required to use _reboot() system call. 13 | #define LINUX_REBOOT_MAGIC2A 85072278 14 | /// Magic values required to use _reboot() system call. 15 | #define LINUX_REBOOT_MAGIC2B 369367448 16 | /// Magic values required to use _reboot() system call. 17 | #define LINUX_REBOOT_MAGIC2C 537993216 18 | 19 | // Commands accepted by the _reboot() system call. 20 | /// Restart system using default command and mode. 21 | #define LINUX_REBOOT_CMD_RESTART 0x01234567 22 | /// Stop OS and give system control to ROM monitor, if any. 23 | #define LINUX_REBOOT_CMD_HALT 0xCDEF0123 24 | /// Ctrl-Alt-Del sequence causes RESTART command. 25 | #define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF 26 | /// Ctrl-Alt-Del sequence sends SIGINT to init task. 27 | #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000 28 | /// Stop OS and remove all power from system, if possible. 29 | #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC 30 | /// Restart system using given command string. 31 | #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 32 | /// Suspend system using software suspend if compiled in. 33 | #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 34 | /// Restart system using a previously loaded Linux kernel 35 | #define LINUX_REBOOT_CMD_KEXEC 0x45584543 36 | 37 | /// @brief Reboots the system, or enables/disables the reboot keystroke. 38 | /// @param magic1 fails (with the error EINVAL) unless equals LINUX_REBOOT_MAGIC1. 39 | /// @param magic2 fails (with the error EINVAL) unless equals LINUX_REBOOT_MAGIC2. 40 | /// @param cmd The command to send to the reboot. 41 | /// @param arg Argument passed with some specific commands. 42 | /// @return For the values of cmd that stop or restart the system, a 43 | /// successful call to reboot() does not return. For the other cmd 44 | /// values, zero is returned on success. In all cases, -1 is 45 | /// returned on failure, and errno is set appropriately. 46 | int reboot(int magic1, int magic2, unsigned int cmd, void *arg); 47 | -------------------------------------------------------------------------------- /libc/inc/sys/types.h: -------------------------------------------------------------------------------- 1 | /// @file types.h 2 | /// @brief Collection of Kernel datatype 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief The type of process id. 9 | typedef signed int pid_t; 10 | /// @brief The type of process user variable. 11 | typedef unsigned int user_t; 12 | /// @brief The type of process status. 13 | typedef unsigned int status_t; 14 | /// @brief Type for system keys. 15 | typedef int key_t; 16 | /// @brief Represents the number of hard links to a file. 17 | typedef unsigned int nlink_t; 18 | /// @brief Represents the preferred block size for filesystem I/O. 19 | typedef long blksize_t; 20 | /// @brief Represents the number of 512B blocks allocated to a file. 21 | typedef long blkcnt_t; 22 | 23 | /// Defines the list of flags of a process. 24 | typedef enum eflags_list { 25 | /// Carry flag. 26 | EFLAG_CF = (1 << 0), 27 | 28 | /// Parity flag. 29 | EFLAG_PF = (1 << 2), 30 | 31 | /// Auxiliary carry flag. 32 | EFLAG_AF = (1 << 4), 33 | 34 | /// Zero flag. 35 | EFLAG_ZF = (1 << 6), 36 | 37 | /// Sign flag. 38 | EFLAG_SF = (1 << 7), 39 | 40 | /// Trap flag. 41 | EFLAG_TF = (1 << 8), 42 | 43 | /// Interrupt enable flag. 44 | EFLAG_IF = (1 << 9), 45 | 46 | /// Direction flag. 47 | EFLAG_DF = (1 << 10), 48 | 49 | /// Overflow flag. 50 | EFLAG_OF = (1 << 11), 51 | 52 | /// Nested task flag. 53 | EFLAG_NT = (1 << 14), 54 | 55 | /// Resume flag. 56 | EFLAG_RF = (1 << 16), 57 | 58 | /// Virtual 8086 mode flag. 59 | EFLAG_VM = (1 << 17), 60 | 61 | /// Alignment check flag (486+). 62 | EFLAG_AC = (1 << 18), 63 | 64 | /// Virutal interrupt flag. 65 | EFLAG_VIF = (1 << 19), 66 | 67 | /// Virtual interrupt pending flag. 68 | EFLAG_VIP = (1 << 20), 69 | 70 | /// ID flag. 71 | EFLAG_ID = (1 << 21), 72 | } eflags_list; 73 | -------------------------------------------------------------------------------- /libc/inc/sys/utsname.h: -------------------------------------------------------------------------------- 1 | /// @file utsname.h 2 | /// @brief Functions used to provide information about the machine & OS. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// Maximum length of the string used by utsname. 9 | #define SYS_LEN 257 10 | 11 | /// @brief Holds information concerning the machine and the os. 12 | typedef struct utsname { 13 | /// The name of the system. 14 | char sysname[SYS_LEN]; 15 | /// The name of the node. 16 | char nodename[SYS_LEN]; 17 | /// Operating system release (e.g., "2.6.28"). 18 | char release[SYS_LEN]; 19 | /// The version of the OS. 20 | char version[SYS_LEN]; 21 | /// The name of the machine. 22 | char machine[SYS_LEN]; 23 | } utsname_t; 24 | 25 | /// @brief Returns system information in the structure pointed to by buf. 26 | /// @param buf Buffer where the info will be placed. 27 | /// @return 0 on success, a negative value on failure. 28 | int uname(utsname_t *buf); 29 | -------------------------------------------------------------------------------- /libc/inc/termios.h: -------------------------------------------------------------------------------- 1 | /// @file termios.h 2 | /// @brief Defines the termios functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "bits/termios-struct.h" 9 | 10 | /// @brief Put the state of FD into *TERMIOS_P. 11 | /// @param fd 12 | /// @param termios_p 13 | /// @return 14 | extern int tcgetattr(int fd, termios_t *termios_p); 15 | 16 | /// @brief Set the state of FD to *TERMIOS_P. 17 | /// @param fd 18 | /// @param optional_actions 19 | /// @param termios_p 20 | /// @return 21 | extern int tcsetattr(int fd, int optional_actions, const termios_t *termios_p); 22 | -------------------------------------------------------------------------------- /libc/src/abort.c: -------------------------------------------------------------------------------- 1 | /// @file abort.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "grp.h" 7 | #include "signal.h" 8 | #include "stdio.h" 9 | #include "stdlib.h" 10 | #include "string.h" 11 | #include "unistd.h" 12 | 13 | /// @brief Since there could be signal handlers listening for the abort, we need 14 | /// to keep track at which stage of the abort we are. 15 | static int stage = 0; 16 | 17 | void abort(void) 18 | { 19 | struct sigaction action; 20 | sigset_t sigset; 21 | 22 | /* Unblock SIGABRT. */ 23 | if (stage == 0) { 24 | ++stage; 25 | 26 | sigemptyset(&sigset); 27 | sigaddset(&sigset, SIGABRT); 28 | sigprocmask(SIG_UNBLOCK, &sigset, 0); 29 | } 30 | 31 | /* Send signal which possibly calls a user handler. */ 32 | if (stage == 1) { 33 | // We must allow recursive calls of abort 34 | int save_stage = stage; 35 | 36 | stage = 0; 37 | kill(getpid(), SIGABRT); 38 | stage = save_stage + 1; 39 | } 40 | 41 | /* There was a handler installed. Now remove it. */ 42 | if (stage == 2) { 43 | ++stage; 44 | 45 | memset(&action, 0, sizeof(action)); 46 | 47 | action.sa_handler = SIG_DFL; 48 | sigemptyset(&action.sa_mask); 49 | action.sa_flags = 0; 50 | 51 | sigaction(SIGABRT, &action, NULL); 52 | } 53 | 54 | /* Try again. */ 55 | if (stage == 3) { 56 | ++stage; 57 | 58 | kill(getpid(), SIGABRT); 59 | } 60 | 61 | /* Now try to abort using the system specific command. */ 62 | if (stage == 4) { 63 | ++stage; 64 | 65 | __asm__ __volatile__("hlt"); 66 | } 67 | 68 | /* If we can't signal ourselves and the abort instruction failed, exit. */ 69 | if (stage == 5) { 70 | ++stage; 71 | 72 | exit(127); 73 | } 74 | 75 | // If even this fails try to use the provided instruction to crash 76 | // or otherwise make sure we never return. 77 | #pragma clang diagnostic push 78 | #pragma ide diagnostic ignored "EndlessLoop" 79 | while (1) { 80 | __asm__ __volatile__("hlt"); 81 | }; 82 | #pragma clang diagnostic pop 83 | } 84 | -------------------------------------------------------------------------------- /libc/src/assert.c: -------------------------------------------------------------------------------- 1 | /// @file assert.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "assert.h" 7 | #include "stdio.h" 8 | #include "stdlib.h" 9 | 10 | void __assert_fail(const char *assertion, const char *file, const char *function, unsigned int line) 11 | { 12 | printf( 13 | "\n=== ASSERTION FAILED ===\n" 14 | "Assertion: %s\n" 15 | "Location : %s:%d\n" 16 | "Function : %s\n\n", 17 | assertion, file, line, (function ? function : "Unknown function")); 18 | abort(); 19 | } 20 | -------------------------------------------------------------------------------- /libc/src/crt0.S: -------------------------------------------------------------------------------- 1 | extern main 2 | extern __libc_start_main 3 | global _start 4 | 5 | ; ----------------------------------------------------------------------------- 6 | ; SECTION (text) 7 | ; ----------------------------------------------------------------------------- 8 | section .text 9 | _start: ; _start is the entry point known to the linker 10 | mov ebp, 0 ; Set ebp to 0 as x86 programs require 11 | push main ; Push the pointer to `main` to the stack. 12 | call __libc_start_main ; Call the libc initialization function. 13 | mov ebx, eax ; Move `main` return value to ebx. 14 | mov eax, 1 ; Call the `exit` function by using `int 80` (i.e., a system call) 15 | int 0x80 16 | 17 | ; ----------------------------------------------------------------------------- 18 | ; SECTION (note) - Inform the linker that the stack does not need to be executable 19 | ; ----------------------------------------------------------------------------- 20 | section .note.GNU-stack 21 | -------------------------------------------------------------------------------- /libc/src/ctype.c: -------------------------------------------------------------------------------- 1 | /// @file ctype.c 2 | /// @brief Functions related to character handling. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "ctype.h" 7 | 8 | /// Distance from a uppercase character to the correspondent lowercase in ASCII. 9 | #define OFFSET 32 10 | 11 | int isdigit(int c) { return (c >= 48 && c <= 57); } 12 | 13 | int isalpha(int c) { return ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)); } 14 | 15 | int iscntrl(int c) { return ((c >= 0x00 && c <= 0x1F) || (c == 0x7F)); } 16 | 17 | int isalnum(int c) { return (isalpha(c) || isdigit(c)); } 18 | 19 | int isxdigit(int c) { return (isdigit(c) || (c >= 65 && c <= 70)); } 20 | 21 | int islower(int c) { return (c >= 97 && c <= 122); } 22 | 23 | int isupper(int c) { return (c >= 65 && c <= 90); } 24 | 25 | int tolower(int c) 26 | { 27 | if (isalpha(c) == 0 || islower(c)) { 28 | return c; 29 | } 30 | 31 | return c + OFFSET; 32 | } 33 | 34 | int toupper(int c) 35 | { 36 | if (isalpha(c) == 0 || isupper(c)) { 37 | return c; 38 | } 39 | 40 | return c - OFFSET; 41 | } 42 | 43 | int isspace(int c) { return (c == ' '); } 44 | -------------------------------------------------------------------------------- /libc/src/err.c: -------------------------------------------------------------------------------- 1 | /// @file err.h 2 | /// @brief Contains err functions 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void verr(int status, const char *format, va_list args) 13 | { 14 | if (format) { 15 | vfprintf(STDERR_FILENO, format, args); 16 | fprintf(STDERR_FILENO, ": "); 17 | } 18 | perror(0); 19 | exit(status); 20 | } 21 | 22 | void verrx(int status, const char *format, va_list args) 23 | { 24 | if (format) { 25 | vfprintf(STDERR_FILENO, format, args); 26 | } 27 | fprintf(STDERR_FILENO, "\n"); 28 | exit(status); 29 | } 30 | 31 | void err(int status, const char *format, ...) 32 | { 33 | va_list ap; 34 | va_start(ap, format); 35 | verr(status, format, ap); 36 | va_end(ap); 37 | } 38 | 39 | void errx(int status, const char *format, ...) 40 | { 41 | va_list ap; 42 | va_start(ap, format); 43 | verrx(status, format, ap); 44 | va_end(ap); 45 | } 46 | -------------------------------------------------------------------------------- /libc/src/io/mm_io.c: -------------------------------------------------------------------------------- 1 | /// @file mm_io.c 2 | /// @brief Memory Mapped IO functions implementation. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "io/mm_io.h" 7 | 8 | inline uint8_t in_memb(uint32_t addr) { return *((uint8_t *)(addr)); } 9 | 10 | inline uint16_t in_mems(uint32_t addr) { return *((uint16_t *)(addr)); } 11 | 12 | inline uint32_t in_meml(uint32_t addr) { return *((uint32_t *)(addr)); } 13 | 14 | inline void out_memb(uint32_t addr, uint8_t value) { (*((uint8_t *)(addr))) = (value); } 15 | 16 | inline void out_mems(uint32_t addr, uint16_t value) { (*((uint16_t *)(addr))) = (value); } 17 | 18 | inline void out_meml(uint32_t addr, uint32_t value) { (*((uint32_t *)(addr))) = (value); } 19 | -------------------------------------------------------------------------------- /libc/src/libc_start.c: -------------------------------------------------------------------------------- 1 | /// @file libc_start.c 2 | /// @brief Contains the programs initialization procedure. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "assert.h" 7 | #include "errno.h" 8 | #include "stdlib.h" 9 | #include "string.h" 10 | #include "system/syscall_types.h" 11 | #include "unistd.h" 12 | 13 | /// @brief Reference to the `environ` variable in `setenv.c`. 14 | extern char **environ; 15 | 16 | /// @brief The entry point to every program. 17 | /// @param main Pointer to the main function. 18 | /// @param argc The number of arguments. 19 | /// @param argv The pointer to the arguments. 20 | /// @param envp The pointer to the environmental variables. 21 | /// @return The return of the `main` function. 22 | int __libc_start_main(int (*main)(int, char **, char **), int argc, char *argv[], char *envp[]) 23 | { 24 | //dbg_print("== START %-30s =======================================\n", argv[0]); 25 | //dbg_print("__libc_start_main(%p, %d, %p, %p)\n", main, argc, argv, envp); 26 | assert(main && "There is no `main` function."); 27 | assert(argv && "There is no `argv` array."); 28 | assert(envp && "There is no `envp` array."); 29 | //dbg_print("environ : %p\n", environ); 30 | // Copy the environ. 31 | environ = envp; 32 | // Call the main function. 33 | int result = main(argc, argv, envp); 34 | // Free the environ. 35 | //dbg_print("== END %-30s =======================================\n", argv[0]); 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /libc/src/sched.c: -------------------------------------------------------------------------------- 1 | /// @file sched.c 2 | /// @brief Function for managing scheduler. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "sched.h" 7 | #include "errno.h" 8 | #include "system/syscall_types.h" 9 | 10 | // _syscall2(int, sched_setparam, pid_t, pid, const sched_param_t *, param) 11 | int sched_setparam(pid_t pid, const sched_param_t *param) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, sched_setparam, pid, param); 15 | __syscall_return(int, __res); 16 | } 17 | 18 | // _syscall2(int, sched_getparam, pid_t, pid, sched_param_t *, param) 19 | int sched_getparam(pid_t pid, sched_param_t *param) 20 | { 21 | long __res; 22 | __inline_syscall_2(__res, sched_getparam, pid, param); 23 | __syscall_return(int, __res); 24 | } 25 | 26 | // _syscall0(int, waitperiod) 27 | int waitperiod(void) 28 | { 29 | long __res; 30 | __inline_syscall_0(__res, waitperiod); 31 | __syscall_return(int, __res); 32 | } 33 | -------------------------------------------------------------------------------- /libc/src/sys/errno.c: -------------------------------------------------------------------------------- 1 | /// @file errno.c 2 | /// @brief Stores the error number. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | 8 | /// @brief Returns the error number for the current process. 9 | /// @return Pointer to the error number. 10 | int *__geterrno(void) 11 | { 12 | static int _errno = 0; 13 | return &_errno; 14 | } 15 | -------------------------------------------------------------------------------- /libc/src/sys/ioctl.c: -------------------------------------------------------------------------------- 1 | /// @file ioctl.c 2 | /// @brief Input/Output ConTroL (IOCTL) functions implementation. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "sys/ioctl.h" 7 | #include "errno.h" 8 | #include "system/syscall_types.h" 9 | 10 | // _syscall3(long, ioctl, int, fd, unsigned int, request, unsigned long, data) 11 | long ioctl(int fd, unsigned int request, unsigned long data) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, ioctl, fd, request, data); 15 | __syscall_return(long, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/sys/mman.c: -------------------------------------------------------------------------------- 1 | /// @file mman.c 2 | /// @brief Functions for managing mappings in virtual address space. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "sys/mman.h" 7 | #include "errno.h" 8 | #include "system/syscall_types.h" 9 | #include "unistd.h" 10 | 11 | #if 0 12 | 13 | // _syscall6(void *, mmap, void *, addr, size_t, length, int, prot, int, flags, int, fd, off_t, offset) 14 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) 15 | { 16 | long __res; 17 | __inline_syscall_6(__res, mmap, addr, length, prot, flags, fd, offset); 18 | __syscall_return(void *, __res); 19 | } 20 | 21 | // _syscall2(int, munmap, void *, addr, size_t, length) 22 | int munmap(void *addr, size_t length) 23 | { 24 | long __res; 25 | __inline_syscall_2(__res, munmap, addr, length); 26 | __syscall_return(int, __res); 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /libc/src/sys/unistd.c: -------------------------------------------------------------------------------- 1 | /// @file unistd.c 2 | /// @brief Functions used to manage files. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "unistd.h" 7 | #include "limits.h" 8 | #include "stdio.h" 9 | #include "string.h" 10 | 11 | #if 0 12 | #include "vfs.h" 13 | 14 | int rmdir(const char *path) 15 | { 16 | char absolute_path[PATH_MAX]; 17 | 18 | get_absolute_normalized_path(path, absolute_path); 19 | 20 | int32_t mp_id = get_mountpoint_id(absolute_path); 21 | if (mp_id < 0) { 22 | printf("rmdir: failed to remove '%s':" 23 | "Cannot find mount-point\n", 24 | path); 25 | 26 | return -1; 27 | } 28 | 29 | if (mountpoint_list[mp_id].dir_op.rmdir_f == NULL) { 30 | return -1; 31 | } 32 | 33 | return mountpoint_list[mp_id].dir_op.rmdir_f(absolute_path); 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /libc/src/sys/utsname.c: -------------------------------------------------------------------------------- 1 | /// @file utsname.c 2 | /// @brief Functions used to provide information about the machine & OS. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "sys/utsname.h" 7 | #include "errno.h" 8 | #include "stddef.h" 9 | #include "system/syscall_types.h" 10 | 11 | // _syscall1(int, uname, utsname_t *, buf) 12 | 13 | int uname(utsname_t *buf) 14 | { 15 | long __res; 16 | __inline_syscall_1(__res, uname, buf); 17 | __syscall_return(int, __res); 18 | } 19 | -------------------------------------------------------------------------------- /libc/src/termios.c: -------------------------------------------------------------------------------- 1 | /// @file termios.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "termios.h" 7 | #include "bits/ioctls.h" 8 | #include "errno.h" 9 | #include "system/syscall_types.h" 10 | 11 | int tcgetattr(int fd, termios_t *termios_p) 12 | { 13 | int retval; 14 | __asm__ volatile("int $0x80" 15 | : "=a"(retval) 16 | : "0"(__NR_ioctl), "b"((long)(fd)), "c"((long)(TCGETS)), "d"((long)(termios_p))); 17 | if (retval < 0) { 18 | errno = -retval; 19 | retval = -1; 20 | } 21 | return retval; 22 | } 23 | 24 | int tcsetattr(int fd, int optional_actions, const termios_t *termios_p) 25 | { 26 | int retval; 27 | __asm__ volatile("int $0x80" 28 | : "=a"(retval) 29 | : "0"(__NR_ioctl), "b"((long)(fd)), "c"((long)(TCSETS)), "d"((long)(termios_p))); 30 | if (retval < 0) { 31 | errno = -retval; 32 | retval = -1; 33 | } 34 | return retval; 35 | } 36 | -------------------------------------------------------------------------------- /libc/src/unistd/chdir.c: -------------------------------------------------------------------------------- 1 | /// @file chdir.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, chdir, const char *, path) 11 | int chdir(const char *path) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, chdir, path); 15 | __syscall_return(int, __res); 16 | } 17 | 18 | // _syscall1(int, fchdir, int, fd) 19 | int fchdir(int fd) 20 | { 21 | long __res; 22 | __inline_syscall_1(__res, fchdir, fd); 23 | __syscall_return(int, __res); 24 | } 25 | -------------------------------------------------------------------------------- /libc/src/unistd/chmod.c: -------------------------------------------------------------------------------- 1 | /// @file chmod.c 2 | /// @brief 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, chmod, const char *, pathname, mode_t, mode) 11 | int chmod(const char *pathname, mode_t mode) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, chmod, pathname, mode); 15 | __syscall_return(int, __res); 16 | } 17 | 18 | // _syscall2(int, fchmod, int, fd, mode_t, mode) 19 | int fchmod(int fd, mode_t mode) 20 | { 21 | long __res; 22 | __inline_syscall_2(__res, fchmod, fd, mode); 23 | __syscall_return(int, __res); 24 | } 25 | -------------------------------------------------------------------------------- /libc/src/unistd/chown.c: -------------------------------------------------------------------------------- 1 | /// @file chown.c 2 | /// @brief 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(int, chown, const char *, pathname, uid_t, owner, gid_t, group) 11 | int chown(const char *pathname, uid_t owner, gid_t group) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, chown, pathname, owner, group); 15 | __syscall_return(int, __res); 16 | } 17 | 18 | // _syscall3(int, lchown, const char *, pathname, uid_t, owner, gid_t, group) 19 | int lchown(const char *pathname, uid_t owner, gid_t group) 20 | { 21 | long __res; 22 | __inline_syscall_3(__res, lchown, pathname, owner, group); 23 | __syscall_return(int, __res); 24 | } 25 | 26 | // _syscall3(int, fchown, int, fd, uid_t, owner, gid_t, group) 27 | int fchown(int fd, uid_t owner, gid_t group) 28 | { 29 | long __res; 30 | __inline_syscall_3(__res, fchown, fd, owner, group); 31 | __syscall_return(int, __res); 32 | } 33 | -------------------------------------------------------------------------------- /libc/src/unistd/close.c: -------------------------------------------------------------------------------- 1 | /// @file close.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, close, int, fd) 11 | int close(int fd) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, close, fd); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/creat.c: -------------------------------------------------------------------------------- 1 | /// @file creat.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, creat, const char *, pathname, mode_t, mode) 11 | int creat(const char *pathname, mode_t mode) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, creat, pathname, mode); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/dup.c: -------------------------------------------------------------------------------- 1 | /// @file dup.c 2 | /// @brief 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, dup, int, fd) 11 | int dup(int fd) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, dup, fd); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/exit.c: -------------------------------------------------------------------------------- 1 | /// @file exit.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "system/syscall_types.h" 7 | #include "unistd.h" 8 | 9 | void exit(int status) 10 | { 11 | long __res; 12 | __inline_syscall_1(__res, exit, status); 13 | // The process never returns from this system call! 14 | } 15 | -------------------------------------------------------------------------------- /libc/src/unistd/fcntl.c: -------------------------------------------------------------------------------- 1 | /// @file fcntl.c 2 | /// @brief Input/Output ConTroL (IOCTL) functions implementation. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "fcntl.h" 7 | #include "errno.h" 8 | #include "system/syscall_types.h" 9 | 10 | // _syscall3(long, fcntl, int, fd, unsigned int, request, unsigned long, data) 11 | long fcntl(int fd, unsigned int request, unsigned long data) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, fcntl, fd, request, data); 15 | __syscall_return(long, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/fork.c: -------------------------------------------------------------------------------- 1 | /// @file fork.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(pid_t, fork) 11 | pid_t fork(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, fork); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getcwd.c: -------------------------------------------------------------------------------- 1 | /// @file getcwd.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(char *, getcwd, char *, buf, size_t, size) 11 | char *getcwd(char *buf, size_t size) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, getcwd, buf, size); 15 | __syscall_return(char *, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getdents.c: -------------------------------------------------------------------------------- 1 | /// @file getdents.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "dirent.h" 7 | #include "errno.h" 8 | #include "system/syscall_types.h" 9 | #include "unistd.h" 10 | 11 | // _syscall3(ssize_t, getdents, int, fd, dirent_t *, dirp, unsigned int, count) 12 | ssize_t getdents(int fd, dirent_t *dirp, unsigned int count) 13 | { 14 | long __res; 15 | __inline_syscall_3(__res, getdents, fd, dirp, count); 16 | __syscall_return(ssize_t, __res); 17 | } 18 | -------------------------------------------------------------------------------- /libc/src/unistd/getgid.c: -------------------------------------------------------------------------------- 1 | /// @file getgid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(pid_t, getgid) 11 | pid_t getgid(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, getgid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | 18 | // _syscall0(gid_t, getegid) 19 | gid_t getegid(void) 20 | { 21 | long __res; 22 | __inline_syscall_0(__res, getegid); 23 | __syscall_return(gid_t, __res); 24 | } 25 | -------------------------------------------------------------------------------- /libc/src/unistd/getpgid.c: -------------------------------------------------------------------------------- 1 | /// @file getpgid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(pid_t, getpgid, pid_t, pid) 11 | pid_t getpgid(pid_t pid) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, getpgid, pid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getpid.c: -------------------------------------------------------------------------------- 1 | /// @file getpid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(pid_t, getpid) 11 | pid_t getpid(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, getpid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getppid.c: -------------------------------------------------------------------------------- 1 | /// @file getppid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(pid_t, getppid) 11 | pid_t getppid(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, getppid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getsid.c: -------------------------------------------------------------------------------- 1 | /// @file getsid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(pid_t, getsid, pid_t, pid) 11 | pid_t getsid(pid_t pid) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, getsid, pid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/getuid.c: -------------------------------------------------------------------------------- 1 | /// @file getuid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(uid_t, getuid) 11 | uid_t getuid(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, getuid); 15 | __syscall_return(uid_t, __res); 16 | } 17 | 18 | // _syscall0(uid_t, geteuid) 19 | uid_t geteuid(void) 20 | { 21 | long __res; 22 | __inline_syscall_0(__res, geteuid); 23 | __syscall_return(uid_t, __res); 24 | } 25 | -------------------------------------------------------------------------------- /libc/src/unistd/interval.c: -------------------------------------------------------------------------------- 1 | /// @file interval.c 2 | /// @brief Function for setting allarms. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(unsigned, alarm, int, seconds) 11 | unsigned alarm(int seconds) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, alarm, seconds); 15 | __syscall_return(unsigned, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/kill.c: -------------------------------------------------------------------------------- 1 | /// @file kill.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, kill, pid_t, pid, int, sig) 11 | int kill(pid_t pid, int sig) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, kill, pid, sig); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/lseek.c: -------------------------------------------------------------------------------- 1 | /// @file open.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(off_t, lseek, int, fd, off_t, offset, int, whence) 11 | off_t lseek(int fd, off_t offset, int whence) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, lseek, fd, offset, whence); 15 | __syscall_return(off_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/mkdir.c: -------------------------------------------------------------------------------- 1 | /// @file mkdir.c 2 | /// @brief Make directory functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, mkdir, const char *, path, mode_t, mode) 11 | int mkdir(const char *path, mode_t mode) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, mkdir, path, mode); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/nice.c: -------------------------------------------------------------------------------- 1 | /// @file nice.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, nice, int, inc) 11 | int nice(int inc) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, nice, inc); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/open.c: -------------------------------------------------------------------------------- 1 | /// @file open.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(int, open, const char *, pathname, int, flags, mode_t, mode) 11 | int open(const char *pathname, int flags, mode_t mode) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, open, pathname, flags, mode); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/pipe.c: -------------------------------------------------------------------------------- 1 | /// @file pipe.c 2 | /// @brief System call wrapper for creating a pipe 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, pipe, int *, fds) 11 | int pipe(int fds[2]) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, pipe, fds); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/read.c: -------------------------------------------------------------------------------- 1 | /// @file read.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(ssize_t, read, int, fd, void *, buf, size_t, nbytes) 11 | ssize_t read(int fd, void *buf, size_t nbytes) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, read, fd, buf, nbytes); 15 | __syscall_return(ssize_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/readlink.c: -------------------------------------------------------------------------------- 1 | /// @file readlink.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(int, readlink, const char *, path, char *, buffer, size_t, bufsize) 11 | int readlink(const char *path, char *buffer, size_t bufsize) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, readlink, path, buffer, bufsize); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/reboot.c: -------------------------------------------------------------------------------- 1 | /// @file reboot.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, void *, arg) 11 | int reboot(int magic1, int magic2, unsigned int cmd, void *arg) 12 | { 13 | long __res; 14 | __inline_syscall_4(__res, reboot, magic1, magic2, cmd, arg); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/rmdir.c: -------------------------------------------------------------------------------- 1 | /// @file rmdir.c 2 | /// @brief Make directory functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, rmdir, const char *, path) 11 | int rmdir(const char *path) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, rmdir, path); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/setgid.c: -------------------------------------------------------------------------------- 1 | /// @file setgid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "system/syscall_types.h" 7 | 8 | #include "errno.h" 9 | #include "unistd.h" 10 | 11 | // _syscall1(int, setgid, pid_t, gid) 12 | int setgid(gid_t gid) 13 | { 14 | long __res; 15 | __inline_syscall_1(__res, setgid, gid); 16 | __syscall_return(int, __res); 17 | } 18 | 19 | // _syscall2(int, setregid, gid_t, rgid, gid_t, egid) 20 | int setregid(gid_t rgid, gid_t egid) 21 | { 22 | long __res; 23 | __inline_syscall_2(__res, setregid, rgid, egid); 24 | __syscall_return(int, __res); 25 | } 26 | -------------------------------------------------------------------------------- /libc/src/unistd/setpgid.c: -------------------------------------------------------------------------------- 1 | /// @file setpgid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, setpgid, pid_t, pid, pid_t, pgid) 11 | int setpgid(pid_t pid, pid_t pgid) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, setpgid, pid, pgid); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/setsid.c: -------------------------------------------------------------------------------- 1 | /// @file setsid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall0(pid_t, setsid) 11 | pid_t setsid(void) 12 | { 13 | long __res; 14 | __inline_syscall_0(__res, setsid); 15 | __syscall_return(pid_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/setuid.c: -------------------------------------------------------------------------------- 1 | /// @file setuid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, setuid, uid_t, uid) 11 | int setuid(uid_t uid) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, setuid, uid); 15 | __syscall_return(int, __res); 16 | } 17 | 18 | // _syscall2(int, setreuid, uid_t, ruid, uid_t, euid) 19 | int setreuid(uid_t ruid, uid_t euid) 20 | { 21 | long __res; 22 | __inline_syscall_2(__res, setreuid, ruid, euid); 23 | __syscall_return(int, __res); 24 | } 25 | -------------------------------------------------------------------------------- /libc/src/unistd/stat.c: -------------------------------------------------------------------------------- 1 | /// @file stat.c 2 | /// @brief Stat functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | #include "sys/stat.h" 11 | 12 | // _syscall2(int, stat, const char *, path, stat_t *, buf) 13 | int stat(const char *path, stat_t *buf) 14 | { 15 | long __res; 16 | __inline_syscall_2(__res, stat, path, buf); 17 | __syscall_return(int, __res); 18 | } 19 | 20 | // _syscall2(int, fstat, int, fd, stat_t *, buf) 21 | int fstat(int fd, stat_t *buf) 22 | { 23 | long __res; 24 | __inline_syscall_2(__res, fstat, fd, buf); 25 | __syscall_return(int, __res); 26 | } 27 | -------------------------------------------------------------------------------- /libc/src/unistd/symlink.c: -------------------------------------------------------------------------------- 1 | /// @file symlink.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall2(int, symlink, const char *, linkname, const char *, path) 11 | int symlink(const char *linkname, const char *path) 12 | { 13 | long __res; 14 | __inline_syscall_2(__res, symlink, linkname, path); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/unlink.c: -------------------------------------------------------------------------------- 1 | /// @file unlink.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall1(int, unlink, const char *, path) 11 | int unlink(const char *path) 12 | { 13 | long __res; 14 | __inline_syscall_1(__res, unlink, path); 15 | __syscall_return(int, __res); 16 | } 17 | -------------------------------------------------------------------------------- /libc/src/unistd/waitpid.c: -------------------------------------------------------------------------------- 1 | /// @file waitpid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "sys/wait.h" 8 | #include "system/syscall_types.h" 9 | #include "unistd.h" 10 | 11 | #include "strerror.h" 12 | #include "syslog.h" 13 | 14 | pid_t waitpid(pid_t pid, int *status, int options) 15 | { 16 | #if 1 17 | pid_t __res; 18 | int __status = 0; 19 | do { 20 | __inline_syscall_3(__res, waitpid, pid, &__status, options); 21 | if (__res != 0) { 22 | break; 23 | } 24 | if (options && WNOHANG) { 25 | break; 26 | } 27 | } while (1); 28 | 29 | if (status) { 30 | *status = __status; 31 | } 32 | __syscall_return(pid_t, __res); 33 | #else 34 | 35 | pid_t ret; 36 | 37 | while (1) { 38 | __inline_syscall_3(ret, waitpid, pid, status, options); 39 | 40 | // Success: A child process state has changed. 41 | if (ret > 0) { 42 | break; 43 | } 44 | 45 | if (ret < 0) { 46 | __syscall_set_errno(ret); 47 | 48 | // Interrupted by a signal: Retry the syscall. 49 | if (errno == EINTR) { 50 | continue; 51 | } 52 | 53 | // No children to wait for, but WNOHANG allows non-blocking behavior. 54 | if (errno == ECHILD) { 55 | if (options & WNOHANG) { 56 | // Return 0 to indicate no state change. 57 | ret = 0; 58 | break; 59 | } 60 | continue; 61 | } 62 | 63 | // Unrecoverable error: Return -1 and let the caller handle `errno`. 64 | break; 65 | } 66 | } 67 | 68 | // Return the PID of the child whose state has changed (or 0 for WNOHANG). 69 | return ret; 70 | #endif 71 | } 72 | 73 | pid_t wait(int *status) { return waitpid(-1, status, 0); } 74 | -------------------------------------------------------------------------------- /libc/src/unistd/write.c: -------------------------------------------------------------------------------- 1 | /// @file write.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "system/syscall_types.h" 8 | #include "unistd.h" 9 | 10 | // _syscall3(ssize_t, write, int, fd, const void *, buf, size_t, nbytes) 11 | ssize_t write(int fd, const void *buf, size_t nbytes) 12 | { 13 | long __res; 14 | __inline_syscall_3(__res, write, fd, buf, nbytes); 15 | __syscall_return(ssize_t, __res); 16 | } 17 | -------------------------------------------------------------------------------- /mentos/boot.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-i386") 2 | 3 | ENTRY(boot_entry) 4 | 5 | MEMORY { 6 | BOOTLOADER_MEM : ORIGIN = 0x00000000, LENGTH = 128M 7 | } 8 | 9 | SECTIONS 10 | { 11 | . = 0x00100000; 12 | _bootloader_start = .; 13 | .multiboot . : AT(ADDR(.multiboot)) 14 | { 15 | . = ALIGN(4); 16 | _multiboot_header_start = .; 17 | *(.multiboot_header) 18 | _multiboot_header_end = .; 19 | } > BOOTLOADER_MEM 20 | 21 | /* Put the .text section. */ 22 | .text . : AT(ADDR(.text)) 23 | { 24 | _text_start = .; 25 | *(.text) 26 | _text_end = .; 27 | } > BOOTLOADER_MEM 28 | 29 | /* Read-only data. */ 30 | .rodata ALIGN(4K) : AT(ADDR(.rodata)) 31 | { 32 | _rodata_start = .; 33 | *(.rodata) 34 | _rodata_end = .; 35 | } > BOOTLOADER_MEM 36 | 37 | /* Read-write data (initialized) */ 38 | .data ALIGN(4K) : AT(ADDR(.data)) 39 | { 40 | _data_start = .; 41 | *(.data) 42 | _data_end = .; 43 | } > BOOTLOADER_MEM 44 | 45 | /* Read-write data (uninitialized) and stack */ 46 | .bss ALIGN(4K) : AT(ADDR(.bss)) 47 | { 48 | _bss_start = .; 49 | *(.bss*) 50 | _bss_end = .; 51 | } > BOOTLOADER_MEM 52 | 53 | /* Put a symbol end here, it tells us where all the kernel code/data ends, 54 | it means everything after 'end' can be used for something else. */ 55 | _bootloader_end = .; 56 | } 57 | -------------------------------------------------------------------------------- /mentos/inc/drivers/ata/ata.h: -------------------------------------------------------------------------------- 1 | /// @file ata.h 2 | /// @brief Drivers for the Advanced Technology Attachment (ATA) devices. 3 | /// @details 4 | /// IDE is a keyword which refers to the electrical specification of the cables 5 | /// which connect ATA drives (like hard drives) to another device. The drives 6 | /// use the ATA (Advanced Technology Attachment) interface. An IDE cable also 7 | /// can terminate at an IDE card connected to PCI. 8 | /// ATAPI is an extension to ATA (recently renamed to PATA) which adds support 9 | /// for the SCSI command set. 10 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 11 | /// See LICENSE.md for details. 12 | /// @addtogroup drivers Device Drivers 13 | /// @{ 14 | /// @addtogroup ata Advanced Technology Attachment (ATA) 15 | /// @brief Drivers for the Advanced Technology Attachment (ATA) devices. 16 | /// @{ 17 | 18 | #pragma once 19 | 20 | /// @brief Initializes the ATA drivers. 21 | /// @return 0 on success, 1 on error. 22 | int ata_initialize(void); 23 | 24 | /// @brief De-initializes the ATA drivers. 25 | /// @return 0 on success, 1 on error. 26 | int ata_finalize(void); 27 | 28 | /// @} 29 | /// @} 30 | -------------------------------------------------------------------------------- /mentos/inc/drivers/fdc.h: -------------------------------------------------------------------------------- 1 | /// @file fdc.h 2 | /// @brief Definitions about the floppy. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | /// @addtogroup drivers Device Drivers 6 | /// @{ 7 | /// @addtogroup fdc Floppy Disc Controller (FDC) 8 | /// @brief Routines for interfacing with the floppy disc controller. 9 | /// @{ 10 | 11 | #pragma once 12 | 13 | /// @brief Initializes the floppy disk controller. 14 | /// @return 0 on success, 1 on error. 15 | int fdc_initialize(void); 16 | 17 | /// @brief De-initializes the floppy disk controller. 18 | /// @return 0 on success, 1 on error. 19 | int fdc_finalize(void); 20 | 21 | /// @} 22 | /// @} 23 | -------------------------------------------------------------------------------- /mentos/inc/drivers/keyboard/keyboard.h: -------------------------------------------------------------------------------- 1 | /// @file keyboard.h 2 | /// @brief Drivers for the Keyboard devices. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | /// @addtogroup drivers Device Drivers 6 | /// @{ 7 | /// @addtogroup keyboard Keyboard 8 | /// @brief Drivers for the Keyboard devices. 9 | /// @{ 10 | 11 | #pragma once 12 | 13 | #include "kernel.h" 14 | #include "ring_buffer.h" 15 | 16 | DECLARE_FIXED_SIZE_RING_BUFFER(int, keybuffer, 256, -1) 17 | 18 | /// @brief The interrupt service routine of the keyboard. 19 | /// @param f The interrupt stack frame. 20 | void keyboard_isr(pt_regs_t *f); 21 | 22 | /// @brief Enable the keyboard. 23 | void keyboard_enable(void); 24 | 25 | /// @brief Disable the keyboard. 26 | void keyboard_disable(void); 27 | 28 | /// @brief Leds handler. 29 | void keyboard_update_leds(void); 30 | 31 | /// @brief Gets and removes a char from the back of the buffer. 32 | /// @return The extracted character. 33 | int keyboard_pop_back(void); 34 | 35 | /// @brief Gets a char from the back of the buffer. 36 | /// @return The read character. 37 | int keyboard_peek_back(void); 38 | 39 | /// @brief Gets a char from the front of the buffer. 40 | /// @return The read character. 41 | int keyboard_peek_front(void); 42 | 43 | /// @brief Initializes the keyboard drivers. 44 | /// @return 0 on success, 1 on error. 45 | int keyboard_initialize(void); 46 | 47 | /// @brief De-initializes the keyboard drivers. 48 | /// @return 0 on success, 1 on error. 49 | int keyboard_finalize(void); 50 | 51 | /// @} 52 | /// @} 53 | -------------------------------------------------------------------------------- /mentos/inc/drivers/mem.h: -------------------------------------------------------------------------------- 1 | /// @file mem.h 2 | /// @brief Drivers for memory devices 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | /// @addtogroup drivers Device Drivers 6 | /// @{ 7 | /// @addtogroup mem Memory devices 8 | /// @brief Drivers for memory devices. 9 | /// @{ 10 | 11 | #pragma once 12 | 13 | /// @brief Initializes memory devices and registers the null device. 14 | /// 15 | /// @details This function creates the `/dev/null` device, registers the null 16 | /// filesystem type, and mounts the null device to the virtual file system. If 17 | /// any step fails, it logs the error and returns an appropriate error code. 18 | /// 19 | /// @return 0 on success, -ENODEV if device creation fails, 1 if filesystem 20 | /// registration or mounting fails. 21 | int mem_devs_initialize(void); 22 | 23 | /// @} 24 | /// @} 25 | -------------------------------------------------------------------------------- /mentos/inc/drivers/mouse.h: -------------------------------------------------------------------------------- 1 | /// @file mouse.h 2 | /// @brief Driver for *PS2* Mouses. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | /// @addtogroup drivers Device Drivers 6 | /// @{ 7 | /// @addtogroup mouse Mouse 8 | /// @brief Routines for interfacing with the mouse. 9 | /// @{ 10 | 11 | #pragma once 12 | 13 | /* The mouse starts sending automatic packets when the mouse moves or is 14 | * clicked. 15 | */ 16 | #include "kernel.h" 17 | 18 | /// @brief Initializes the mouse. 19 | /// @return 0 on success, 1 on error. 20 | int mouse_initialize(void); 21 | 22 | /// @brief De-initializes the mouse. 23 | /// @return 0 on success, 1 on error. 24 | int mouse_finalize(void); 25 | 26 | /// @} 27 | /// @} 28 | -------------------------------------------------------------------------------- /mentos/inc/drivers/ps2.h: -------------------------------------------------------------------------------- 1 | /// @file ps2.h 2 | /// @brief PS/2 drivers. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Initializes ps2 devices. 9 | /// @return 0 on success, 1 on failure. 10 | int ps2_initialize(void); 11 | 12 | /// @brief Writes a byte of data to the PS/2 device. 13 | /// @details This function waits until the input buffer of the PS/2 controller 14 | /// is empty before sending the specified data byte to the PS/2 data register. 15 | /// @param data The byte of data to be sent to the PS/2 device. 16 | void ps2_write_data(unsigned char data); 17 | 18 | /// @brief Sends a command to the PS/2 controller. 19 | /// @details This function waits until the input buffer of the PS/2 controller 20 | /// is empty before writing the specified command to the PS/2 command register. 21 | /// @param command The command byte to be sent to the PS/2 controller. 22 | void ps2_write_command(unsigned char command); 23 | 24 | /// @brief Reads a byte of data from the PS/2 device. 25 | /// @details This function waits until data is available in the output buffer of 26 | /// the PS/2 controller. Once data is available, it reads and returns the byte 27 | /// from the PS/2 data register. 28 | /// @return The byte of data read from the PS/2 device. 29 | unsigned char ps2_read_data(void); 30 | -------------------------------------------------------------------------------- /mentos/inc/drivers/rtc.h: -------------------------------------------------------------------------------- 1 | /// @file rtc.h 2 | /// @brief Real Time Clock (RTC) driver. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | /// @addtogroup drivers Device Drivers 6 | /// @brief Routines for interfacing with peripheral devices. 7 | /// @{ 8 | /// @addtogroup rtc Real Time Clock (RTC) 9 | /// @brief Routines for interfacing with the real-time clock. 10 | /// @{ 11 | 12 | #pragma once 13 | 14 | #include "time.h" 15 | 16 | /// @brief Copies the global time inside the provided variable. 17 | /// @param time Pointer where we store the global time. 18 | extern void gettime(tm_t *time); 19 | 20 | /// @brief Initializes the Real Time Clock (RTC). 21 | /// @return 0 on success, 1 on error. 22 | int rtc_initialize(void); 23 | 24 | /// @brief De-initializes the Real Time Clock (RTC). 25 | /// @return 0 on success, 1 on error. 26 | int rtc_finalize(void); 27 | 28 | /// @} 29 | /// @} 30 | -------------------------------------------------------------------------------- /mentos/inc/fs/ext2.h: -------------------------------------------------------------------------------- 1 | /// @file ext2.h 2 | /// @brief EXT2 driver. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Initializes the EXT2 drivers. 9 | /// @return 0 on success, 1 on error. 10 | int ext2_initialize(void); 11 | 12 | /// @brief De-initializes the EXT2 drivers. 13 | /// @return 0 on success, 1 on error. 14 | int ext2_finalize(void); 15 | -------------------------------------------------------------------------------- /mentos/inc/fs/namei.h: -------------------------------------------------------------------------------- 1 | /// @file namei.h 2 | /// @brief Headers for path resolution. 3 | /// @details This header provides definitions and function declarations for 4 | /// resolving paths, including symbolic links and handling different flags that 5 | /// control the behavior of the path resolution process. 6 | /// @copyright (c) 2024 This file is distributed under the MIT License. 7 | /// See LICENSE.md for details. 8 | 9 | #pragma once 10 | 11 | #include "stddef.h" 12 | 13 | /// Flag to remove any trailing slash from the path. 14 | #define REMOVE_TRAILING_SLASH 1 << 0 15 | /// Flag to follow symbolic links during path resolution. 16 | #define FOLLOW_LINKS 1 << 1 17 | /// Flag to create the last component of the path if it doesn't exist. 18 | #define CREAT_LAST_COMPONENT 1 << 2 19 | 20 | /// @brief Resolve the given path by following all symbolic links. 21 | /// 22 | /// @details This function resolves a file path, following any symbolic links 23 | /// encountered along the way, and returns the absolute path. The behavior can 24 | /// be controlled with flags such as whether to follow symbolic links and how to 25 | /// handle trailing slashes. 26 | /// 27 | /// @param path The path to resolve, can include symbolic links. 28 | /// @param buffer The buffer where the resolved absolute path will be stored. 29 | /// @param buflen The size of the buffer, which should be large enough to hold the resolved path. 30 | /// @param flags The flags controlling the behavior of path resolution (e.g., following symlinks, relative/absolute paths). 31 | /// @return 1 on success, negative errno on failure (e.g., -ENOENT if the path is not found). 32 | int resolve_path(const char *path, char *buffer, size_t buflen, int flags); 33 | -------------------------------------------------------------------------------- /mentos/inc/io/proc_modules.h: -------------------------------------------------------------------------------- 1 | /// @file proc_modules.h 2 | /// @brief Contains functions for managing procfs filesystems. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "fs/vfs.h" 9 | 10 | /// @brief Initialize the procfs video files. 11 | /// @return 0 on success, 1 on failure. 12 | int procv_module_init(void); 13 | 14 | /// @brief Initialize the procfs system files. 15 | /// @return 0 on success, 1 on failure. 16 | int procs_module_init(void); 17 | 18 | /// @brief Initializes the scheduler feedback system. 19 | /// @return 0 on success, 1 on failure. 20 | int procfb_module_init(void); 21 | 22 | /// @brief Initializes the IPC information system. 23 | /// @return 0 on success, 1 on failure. 24 | int procipc_module_init(void); 25 | -------------------------------------------------------------------------------- /mentos/inc/ipc/ipc.h: -------------------------------------------------------------------------------- 1 | /// @file ipc.h 2 | /// @brief Vital IPC structures and functions kernel side. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "sys/ipc.h" 9 | 10 | #ifndef __KERNEL__ 11 | #error "How did you include this file... include `libc/inc/sys/ipc.h` instead!" 12 | #endif 13 | 14 | /// @brief Validate IPC permissions based on flags and the given permission structure. 15 | /// @param flags Flags that control the validation behavior. 16 | /// @param perm Pointer to the IPC permission structure to validate. 17 | /// @return 0 if the permissions are valid, or a non-zero value on failure. 18 | int ipc_valid_permissions(int flags, struct ipc_perm *perm); 19 | 20 | /// @brief Register an IPC resource with a given key and mode. 21 | /// @param key The key associated with the IPC resource. 22 | /// @param mode The mode (permissions) for the IPC resource. 23 | /// @return A `struct ipc_perm` representing the registered IPC resource. 24 | struct ipc_perm register_ipc(key_t key, mode_t mode); 25 | 26 | /// @brief Initializes the semaphore system. 27 | /// @return 0 on success, 1 on failure. 28 | int sem_init(void); 29 | 30 | /// @brief Initializes the shared memory system. 31 | /// @return 0 on success, 1 on failure. 32 | int shm_init(void); 33 | 34 | /// @brief Initializes the message queue system. 35 | /// @return 0 on success, 1 on failure. 36 | int msq_init(void); 37 | -------------------------------------------------------------------------------- /mentos/inc/kernel.h: -------------------------------------------------------------------------------- 1 | /// @file kernel.h 2 | /// @brief Kernel generic data structure and functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "stdint.h" 9 | 10 | /// @brief The initial stack pointer. 11 | extern uintptr_t initial_esp; 12 | 13 | /// Kilobytes. 14 | #define K 1024 15 | /// Megabytes. 16 | #define M (1024 * K) 17 | /// Gigabytes. 18 | #define G (1024 * M) 19 | 20 | /// @brief Interrupt stack frame. 21 | /// @details 22 | /// When the CPU moves from Ring3 to Ring0 because of an interrupt, 23 | /// the following registes/values are moved into the kernel's stack 24 | typedef struct pt_regs { 25 | /// FS and GS have no hardware-assigned uses. 26 | uint32_t gs; 27 | /// FS and GS have no hardware-assigned uses. 28 | uint32_t fs; 29 | /// Extra Segment determined by the programmer. 30 | uint32_t es; 31 | /// Data Segment. 32 | uint32_t ds; 33 | /// 32-bit destination register. 34 | uint32_t edi; 35 | /// 32-bit source register. 36 | uint32_t esi; 37 | /// 32-bit base pointer register. 38 | uint32_t ebp; 39 | /// 32-bit stack pointer register. 40 | uint32_t esp; 41 | /// 32-bit base register. 42 | uint32_t ebx; 43 | /// 32-bit data register. 44 | uint32_t edx; 45 | /// 32-bit counter. 46 | uint32_t ecx; 47 | /// 32-bit accumulator register. 48 | uint32_t eax; 49 | /// Interrupt number. 50 | uint32_t int_no; 51 | /// Error code. 52 | uint32_t err_code; 53 | /// Instruction Pointer Register. 54 | uint32_t eip; 55 | /// Code Segment. 56 | uint32_t cs; 57 | /// 32-bit flag register. 58 | uint32_t eflags; 59 | /// User application ESP. 60 | uint32_t useresp; 61 | /// Stack Segment. 62 | uint32_t ss; 63 | } pt_regs_t; 64 | -------------------------------------------------------------------------------- /mentos/inc/klib/compiler.h: -------------------------------------------------------------------------------- 1 | /// @file compiler.h 2 | /// @brief Definition of memory barriers. 3 | /// @details 4 | /// Generally speaking, memory barriers prevent the compiler from merging or 5 | /// refetching reads or writes. Ensuring that the compiler does not fold, spindle, 6 | /// or otherwise mutilate accesses that either do not require ordering or that 7 | /// interact with an explicit memory barrier or atomic instruction that provides 8 | /// the required ordering. 9 | /// 10 | /// Follows an extract from `LINUX KERNEL MEMORY BARRIERS` by: David Howells, 11 | /// Paul E. McKenney, Will Deacon, Peter Zijlstra, available at: 12 | /// https://www.kernel.org/doc/Documentation/memory-barriers.txt 13 | /// 14 | /// Consider the following abstract model of the system: 15 | /// @code 16 | /// : : 17 | /// +-------+ : +--------+ : +-------+ 18 | /// | CPU 1 |<----->| Memory |<----->| CPU 2 | 19 | /// +-------+ : +--------+ : +-------+ 20 | /// ^ : ^ : ^ 21 | /// | : | : | 22 | /// | : v : | 23 | /// | : +--------+ : | 24 | /// +---------->| Device |<----------+ 25 | /// : +--------+ : 26 | /// : : 27 | /// @endcode 28 | /// Each CPU executes a program that generates memory access operations. In the 29 | /// abstract CPU, memory operation ordering is very relaxed, and a CPU may actually 30 | /// perform the memory operations in any order it likes, provided program causality 31 | /// appears to be maintained. Similarly, the compiler may also arrange the 32 | /// instructions it emits in any order it likes, provided it doesn't affect the 33 | /// apparent operation of the program. 34 | /// 35 | /// So in the above diagram, the effects of the memory operations performed by a 36 | /// CPU are perceived by the rest of the system as the operations cross the 37 | /// interface between the CPU and rest of the system (the dotted lines). 38 | /// 39 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 40 | /// See LICENSE.md for details. 41 | 42 | #pragma once 43 | 44 | /// @brief Assign the value to the given variable. 45 | #define WRITE_ONCE(var, val) (*((__volatile__ __typeof__(val) *)(&(var))) = (val)) 46 | 47 | /// @brief Read the value from the given variable. 48 | #define READ_ONCE(var) (*((__volatile__ __typeof__(var) *)(&(var)))) 49 | -------------------------------------------------------------------------------- /mentos/inc/klib/irqflags.h: -------------------------------------------------------------------------------- 1 | /// @file irqflags.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "proc_access.h" 9 | #include "stddef.h" 10 | #include "stdint.h" 11 | 12 | /// @brief Enable IRQs (nested). 13 | /// @details If called after calling irq_disable, this function will not 14 | /// activate IRQs if they were not active before. 15 | /// @param flags the flags to control this behaviour. 16 | inline static void irq_enable(uint8_t flags) 17 | { 18 | if (flags) { 19 | sti(); 20 | } 21 | } 22 | 23 | /// @brief Disable IRQs (nested). 24 | /// @details Disable IRQs when unsure if IRQs were enabled at all. This function 25 | /// together with irq_enable can be used in situations when interrupts 26 | /// shouldn't be activated if they were not activated before calling this 27 | /// function. 28 | /// @return 1 if the IRQ is enable for the CPU. 29 | inline static uint8_t irq_disable(void) 30 | { 31 | size_t flags; 32 | // We are pushing the entire contents of the EFLAGS register onto the stack, 33 | // clearing the interrupt line, and with the pop, getting the current status 34 | // of the flags. 35 | __asm__ __volatile__("pushf; cli; pop %0;" : "=r"(flags) : : "memory"); 36 | return flags & (1 << 9); 37 | } 38 | 39 | /// @brief Determines, if the interrupt flags (IF) is set. 40 | /// @return 1 if the IRQ is enable for the CPU. 41 | inline static uint8_t is_irq_enabled(void) 42 | { 43 | size_t flags; 44 | __asm__ __volatile__("pushf; pop %0;" : "=r"(flags) : : "memory"); 45 | return flags & (1 << 9); 46 | } 47 | -------------------------------------------------------------------------------- /mentos/inc/klib/mutex.h: -------------------------------------------------------------------------------- 1 | /// @file mutex.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "stdint.h" 9 | 10 | /// @brief Structure of a mutex. 11 | typedef struct mutex { 12 | /// The state of the mutex. 13 | uint8_t state; 14 | /// The owner of the mutex. 15 | uint32_t owner; 16 | } mutex_t; 17 | 18 | /// @brief Allows to lock a mutex. 19 | /// @param mutex The mutex to lock. 20 | /// @param owner The one who request the lock. 21 | void mutex_lock(mutex_t *mutex, uint32_t owner); 22 | 23 | /// @brief Unlocks the mutex. 24 | /// @param mutex The mutex to unlock. 25 | void mutex_unlock(mutex_t *mutex); 26 | -------------------------------------------------------------------------------- /mentos/inc/klib/spinlock.h: -------------------------------------------------------------------------------- 1 | /// @file spinlock.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "klib/stdatomic.h" 9 | 10 | /// Determines if the spinlock is free. 11 | #define SPINLOCK_FREE 0 12 | /// Determines if the spinlock is busy. 13 | #define SPINLOCK_BUSY 1 14 | 15 | /// @brief Spinlock structure. 16 | typedef atomic_t spinlock_t; 17 | 18 | /// @brief Initialize the spinlock. 19 | /// @param spinlock The spinlock we initialize. 20 | void spinlock_init(spinlock_t *spinlock); 21 | 22 | /// @brief Try to lock the spinlock. 23 | /// @param spinlock The spinlock we lock. 24 | void spinlock_lock(spinlock_t *spinlock); 25 | 26 | /// @brief Try to unlock the spinlock. 27 | /// @param spinlock The spinlock we unlock. 28 | void spinlock_unlock(spinlock_t *spinlock); 29 | 30 | /// @brief Try to unlock the spinlock. 31 | /// @param spinlock The spinlock we try to block. 32 | /// @return 1 if succeeded, 0 otherwise. 33 | int spinlock_trylock(spinlock_t *spinlock); 34 | -------------------------------------------------------------------------------- /mentos/inc/klib/stack_helper.h: -------------------------------------------------------------------------------- 1 | /// @file stack_helper.h 2 | /// @brief Couple of macros that help accessing the stack. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Access the value of the pointer. 9 | #define __ACCESS_PTR(type, ptr) (*(type *)(ptr)) 10 | /// @brief Moves the pointer down. 11 | #define __MOVE_PTR_DOWN(type, ptr) ((ptr) -= sizeof(type)) 12 | /// @brief Moves the pointer up. 13 | #define __MOVE_PTR_UP(type, ptr) ((ptr) += sizeof(type)) 14 | /// @brief First, it moves the pointer down, and then it pushes the value at that memory location. 15 | #define PUSH_VALUE_ON_STACK(ptr, value) \ 16 | (__ACCESS_PTR(__typeof__(value), __MOVE_PTR_DOWN(__typeof__(value), ptr)) = (value)) 17 | /// @brief First, it access the value at the given memory location, and then it moves the pointer up. 18 | #define POP_VALUE_FROM_STACK(value, ptr) \ 19 | ({ \ 20 | (value) = __ACCESS_PTR(__typeof__(value), ptr); \ 21 | __MOVE_PTR_UP(__typeof__(value), ptr); \ 22 | }) 23 | -------------------------------------------------------------------------------- /mentos/inc/link_access.h: -------------------------------------------------------------------------------- 1 | /// @file link_access.h 2 | /// @brief Set of macros that provide access to linking symbols. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | // #ifdef __APPLE__ 9 | 10 | // /// @brief Define variables pointing to external symbols, specifically 11 | // /// to the .data section of a linked object file. 12 | // #define EXTLD(NAME) extern const unsigned char _section$__DATA__##NAME[]; 13 | // /// Provide access to the .data of the linked object. 14 | // #define LDVAR(NAME) _section$__DATA__##NAME 15 | 16 | // #elif (defined __WIN32__) // mingw 17 | 18 | #if (defined __WIN32__) // mingw 19 | 20 | /// @brief Define variables pointing to external symbols, specifically 21 | /// to the .data section of a linked object file. 22 | #define EXTLD(NAME) \ 23 | extern const unsigned char binary_##NAME##_start[]; \ 24 | extern const unsigned char binary_##NAME##_end[]; \ 25 | extern const unsigned char binary_##NAME##_size[]; 26 | /// Provide access to the .data of the linked object. 27 | #define LDVAR(NAME) binary_##NAME##_start 28 | /// Provides access to the length of the .data section of the linked object. 29 | #define LDLEN(NAME) binary_##NAME##_size 30 | 31 | #else // gnu/linux ld 32 | 33 | /// @brief Define variables pointing to external symbols, specifically 34 | /// to the .data section of a linked object file. 35 | #define EXTLD(NAME) \ 36 | extern const unsigned char _binary_##NAME##_start[]; \ 37 | extern const unsigned char _binary_##NAME##_end[]; \ 38 | extern const unsigned char _binary_##NAME##_size[]; 39 | /// Provides access to the .data of the linked object. 40 | #define LDVAR(NAME) _binary_##NAME##_start 41 | /// Provides access to the length of the .data section of the linked object. 42 | #define LDLEN(NAME) _binary_##NAME##_size 43 | #endif 44 | -------------------------------------------------------------------------------- /mentos/inc/mem/page_fault.h: -------------------------------------------------------------------------------- 1 | /// @file page_fault.h 2 | /// @brief Page fault handler interface. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "kernel.h" 9 | 10 | /// @brief Initializes the page fault handler. 11 | /// @return 0 on success, -1 on failure. 12 | int init_page_fault(void); 13 | 14 | /// @brief Handles a page fault. 15 | /// @param f The interrupt stack frame. 16 | void page_fault_handler(pt_regs_t *f); 17 | -------------------------------------------------------------------------------- /mentos/inc/process/pid_manager.h: -------------------------------------------------------------------------------- 1 | /// @file pid_manager.h 2 | /// @brief Manages the PIDs in the system. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "sys/types.h" 9 | 10 | /// @brief Initializes the PID bitmap, marking all PIDs as free. 11 | void pid_manager_init(void); 12 | 13 | /// @brief Marks a PID as used in the bitmap. 14 | /// @param pid The PID to mark as used. 15 | void pid_manager_mark_used(pid_t pid); 16 | 17 | /// @brief Marks a PID as free in the bitmap. 18 | /// @param pid The PID to mark as free. 19 | void pid_manager_mark_free(pid_t pid); 20 | 21 | /// @brief Returns a unique PID. 22 | /// @return a free PID. 23 | pid_t pid_manager_get_free_pid(void); 24 | -------------------------------------------------------------------------------- /mentos/inc/process/scheduler_feedback.h: -------------------------------------------------------------------------------- 1 | /// @file scheduler_feedback.h 2 | /// @brief Scheduler feedback system for managing tasks and updating scheduling statistics. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "process/process.h" 9 | #include "sys/types.h" 10 | 11 | /// @brief Initialize the scheduler feedback system. 12 | /// @details This function sets up the necessary data structures and mechanisms 13 | /// for the scheduler feedback system. It must be called before any other 14 | /// scheduler feedback operations are performed. 15 | /// @return 1 on success, 0 on failure. 16 | int scheduler_feedback_init(void); 17 | 18 | /// @brief Add the given task to the feedback system. 19 | /// @param task A pointer to the task_struct representing the task to be added. 20 | /// @details This function adds a task to the scheduler feedback system for 21 | /// monitoring and updating its scheduling statistics. 22 | void scheduler_feedback_task_add(task_struct *task); 23 | 24 | /// @brief Removes the given task from the feedback system. 25 | /// @param pid The process ID of the task to remove. 26 | /// @details This function removes the task identified by the given pid from the 27 | /// scheduler feedback system. It should be called when a task is terminated or 28 | /// no longer needs to be monitored. 29 | void scheduler_feedback_task_remove(pid_t pid); 30 | 31 | /// @brief Updates the scheduling statistics for the given task. 32 | /// @param task A pointer to the task_struct representing the task to update. 33 | /// @details This function updates the scheduling statistics for the given task 34 | /// based on its recent behavior (e.g., execution time, priority changes). 35 | void scheduler_feedback_task_update(task_struct *task); 36 | 37 | /// @brief Updates the global scheduler feedback statistics. 38 | /// @details This function is periodically called to update the overall 39 | /// statistics of the scheduler feedback system, adjusting task priorities and 40 | /// managing scheduling decisions for all tasks. 41 | void scheduler_feedback_update(void); 42 | -------------------------------------------------------------------------------- /mentos/inc/resource_tracing.h: -------------------------------------------------------------------------------- 1 | /// @file resource_tracing.h 2 | /// @brief Define the resources tracing system. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Initializes the resource registry and tracker. 9 | void resource_register_init(void); 10 | 11 | /// @brief Registers a new resource with a unique ID and name. 12 | /// @param name The name of the resource to register. 13 | /// @return The unique ID assigned to the resource, or -1 if registration failed. 14 | int register_resource(const char *name); 15 | 16 | /// @brief Retrieves the name of a registered resource. 17 | /// @param id The unique ID of the resource. 18 | /// @return The name of the resource, or NULL if not found. 19 | const char *get_resource_name(int id); 20 | 21 | /// @brief Unregisters a resource by its unique ID. 22 | /// @param id The unique ID of the resource to unregister. 23 | /// @return 0 on success, or -1 if the resource ID was not found. 24 | int unregister_resource(int id); 25 | 26 | /// @brief Prints the current registry of resources. 27 | void print_resource_registry(void); 28 | 29 | /// @brief Adds a resource to the tracking system. 30 | /// @param resource_id The ID of the resource associated with the resource allocation. 31 | /// @param file The file where the resource was allocated. 32 | /// @param line The line number where the resource was allocated. 33 | /// @param ptr The pointer or handle to the resource. 34 | void store_resource_info(int resource_id, const char *file, int line, void *ptr); 35 | 36 | /// @brief Removes a resource from the tracking system. 37 | /// @param ptr The pointer or handle to the resource to remove. 38 | void clear_resource_info(void *ptr); 39 | 40 | /// @brief Checks and prints resource usage for a specific resource ID. 41 | /// @details If resource_id is -1, checks and prints usage for all resources. 42 | /// @param resource_id The ID of the resource to check. Use -1 to check all resources. 43 | /// @param printer A callback function to handle the formatted output for each resource. 44 | void print_resource_usage(int resource_id, const char *(*printer)(void *ptr)); 45 | -------------------------------------------------------------------------------- /mentos/inc/sys/module.h: -------------------------------------------------------------------------------- 1 | /// @file module.h 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | #include "multiboot.h" 9 | #include "stdint.h" 10 | 11 | /// The maximum number of modules. 12 | #define MAX_MODULES 10 13 | 14 | extern multiboot_module_t modules[MAX_MODULES]; 15 | 16 | /// @brief Ininitialize the modules. 17 | /// @param header Multiboot info used to initialize the modules. 18 | /// @return 1 on success, 0 on error. 19 | int init_modules(multiboot_info_t *header); 20 | 21 | /// @brief Relocates modules to virtual mapped low memory, to allow physical 22 | /// unmapping of the first part of the ram. 23 | /// @return 1 on success, 0 on failure. 24 | int relocate_modules(void); 25 | 26 | /// @brief Returns the address where the modules end. 27 | /// @return Address after the modules. 28 | uintptr_t get_address_after_modules(void); 29 | -------------------------------------------------------------------------------- /mentos/inc/system/panic.h: -------------------------------------------------------------------------------- 1 | /// @file panic.h 2 | /// @brief Functions used to manage kernel panic. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Prints the given message and safely stop the execution of the kernel. 9 | /// @param msg The message that has to be shown. 10 | void kernel_panic(const char *msg); 11 | 12 | /// @brief Sends a kernel panic with the given message. 13 | #define TODO(msg) kernel_panic(#msg); 14 | -------------------------------------------------------------------------------- /mentos/inc/system/printk.h: -------------------------------------------------------------------------------- 1 | /// @file printk.h 2 | /// @brief Functions for managing the kernel messages. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// @brief Sends a message to the system log using a specified log level. 9 | /// @param file the name of the file. 10 | /// @param fun the name of the function. 11 | /// @param line the line inside the file. 12 | /// @param log_level the log level. 13 | /// @param format the format to used, see printf. 14 | void sys_syslog(const char *file, const char *fun, int line, short log_level, const char *format); 15 | -------------------------------------------------------------------------------- /mentos/inc/version.h: -------------------------------------------------------------------------------- 1 | /// @file version.h 2 | /// @brief Version information. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #pragma once 7 | 8 | /// The name of the operating system. 9 | #define OS_NAME "MentOS" 10 | 11 | /// The site of the operating system. 12 | #define OS_SITEURL "https://mentos-team.github.io/MentOS" 13 | 14 | /// The email of the reference developer. 15 | #define OS_REF_EMAIL "enry.frak@gmail.com" 16 | 17 | /// Major version of the operating system. 18 | #define OS_MAJOR_VERSION 0 19 | 20 | /// Minor version of the operating system. 21 | #define OS_MINOR_VERSION 9 22 | 23 | /// Micro version of the operating system. 24 | #define OS_MICRO_VERSION 1 25 | 26 | /// Helper to transform the given argument into a string. 27 | #define OS_STR_HELPER(x) #x 28 | 29 | /// Helper to transform the given argument into a string. 30 | #define OS_STR(x) OS_STR_HELPER(x) 31 | 32 | /// Complete version of the operating system. 33 | #define OS_VERSION \ 34 | OS_STR(OS_MAJOR_VERSION) \ 35 | "." OS_STR(OS_MINOR_VERSION) "." OS_STR(OS_MICRO_VERSION) 36 | -------------------------------------------------------------------------------- /mentos/kernel.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-i386") 2 | 3 | ENTRY(kmain) 4 | 5 | MEMORY { 6 | USER_SPACE : ORIGIN = 0x00000000, LENGTH = 3072M 7 | KERNEL_LOWMEM : ORIGIN = 0xC0000000, LENGTH = 896M 8 | KERNEL_HIGHMEM : ORIGIN = 0xF8000000, LENGTH = 128M 9 | } 10 | 11 | 12 | SECTIONS 13 | { 14 | . = 0xC0000000; 15 | /* Put the .text section. */ 16 | .text . : AT(ADDR(.text)) 17 | { 18 | _text_start = .; 19 | EXCLUDE_FILE(*boot.*.o) *(.text) 20 | _text_end = .; 21 | } > KERNEL_LOWMEM 22 | 23 | /* Read-only data. */ 24 | .rodata ALIGN(4K) : AT(ADDR(.rodata)) 25 | { 26 | _rodata_start = .; 27 | EXCLUDE_FILE(*boot.*.o) *(.rodata) 28 | _rodata_end = .; 29 | } > KERNEL_LOWMEM 30 | 31 | /* Read-write data (initialized) */ 32 | .data ALIGN(4K) : AT(ADDR(.data)) 33 | { 34 | _data_start = .; 35 | EXCLUDE_FILE(*boot.*.o) *(.data) 36 | _data_end = .; 37 | } > KERNEL_LOWMEM 38 | 39 | /* Read-write data (uninitialized) and stack */ 40 | .bss ALIGN(4K) : AT(ADDR(.bss)) 41 | { 42 | _bss_start = .; 43 | *(.bss*) 44 | _bss_end = .; 45 | } > KERNEL_LOWMEM 46 | 47 | /* Put a symbol end here, it tells us where all the kernel code/data ends, 48 | it means everything after 'end' can be used for something else. */ 49 | _kernel_end = .; 50 | } 51 | -------------------------------------------------------------------------------- /mentos/src/descriptor_tables/gdt.S: -------------------------------------------------------------------------------- 1 | ; MentOS, The Mentoring Operating system project 2 | ; @file gdt.asm 3 | ; @brief 4 | ; @copyright (c) 2014-2021 This file is distributed under the MIT License. 5 | ; See LICENSE.md for details. 6 | 7 | global gdt_flush ; Allows the C code to call gdt_flush(). 8 | 9 | ; ----------------------------------------------------------------------------- 10 | ; SECTION (text) 11 | ; ----------------------------------------------------------------------------- 12 | section .text 13 | 14 | gdt_flush: 15 | mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter. 16 | lgdt [eax] ; Load the new GDT pointer 17 | 18 | ; The data segments selectors (registers), can be easily modified using 19 | ; simple mov instruction, but the cs can't be used with mov, so you use: 20 | jmp 0x08:flush 21 | ; to load the segment configurations into the the code segment selector. 22 | 23 | flush: 24 | mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment 25 | mov ds, ax ; Load all data segment selectors 26 | mov es, ax 27 | mov fs, ax 28 | mov gs, ax 29 | mov ss, ax 30 | ret 31 | 32 | ; ----------------------------------------------------------------------------- 33 | ; SECTION (note) - Inform the linker that the stack does not need to be executable 34 | ; ----------------------------------------------------------------------------- 35 | section .note.GNU-stack 36 | -------------------------------------------------------------------------------- /mentos/src/descriptor_tables/idt.S: -------------------------------------------------------------------------------- 1 | ; MentOS, The Mentoring Operating system project 2 | ; @file idt.asm 3 | ; @brief 4 | ; @copyright (c) 2014-2021 This file is distributed under the MIT License. 5 | ; See LICENSE.md for details. 6 | 7 | global idt_flush ; Allows the C code to call idt_flush(). 8 | 9 | ; ----------------------------------------------------------------------------- 10 | ; SECTION (text) 11 | ; ----------------------------------------------------------------------------- 12 | section .text 13 | 14 | idt_flush: 15 | mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter. 16 | lidt [eax] ; Load the IDT pointer. 17 | ret 18 | 19 | ; ----------------------------------------------------------------------------- 20 | ; SECTION (note) - Inform the linker that the stack does not need to be executable 21 | ; ----------------------------------------------------------------------------- 22 | section .note.GNU-stack 23 | -------------------------------------------------------------------------------- /mentos/src/descriptor_tables/tss.S: -------------------------------------------------------------------------------- 1 | ; MentOS, The Mentoring Operating system project 2 | ; @file tss.asm 3 | ; @brief 4 | ; @copyright (c) 2014-2021 This file is distributed under the MIT License. 5 | ; See LICENSE.md for details. 6 | 7 | global tss_flush 8 | 9 | ; ----------------------------------------------------------------------------- 10 | ; SECTION (text) 11 | ; ----------------------------------------------------------------------------- 12 | section .text 13 | 14 | tss_flush: 15 | mov ax, 0x28 16 | ltr ax 17 | ret 18 | 19 | ; ----------------------------------------------------------------------------- 20 | ; SECTION (note) - Inform the linker that the stack does not need to be executable 21 | ; ----------------------------------------------------------------------------- 22 | section .note.GNU-stack 23 | -------------------------------------------------------------------------------- /mentos/src/descriptor_tables/tss.c: -------------------------------------------------------------------------------- 1 | /// @file tss.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | // Setup the logging for this file (do this before any other include). 7 | #include "sys/kernel_levels.h" // Include kernel log levels. 8 | #define __DEBUG_HEADER__ "[TSS ]" ///< Change header. 9 | #define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. 10 | #include "io/debug.h" // Include debugging functions. 11 | 12 | #include "descriptor_tables/gdt.h" 13 | #include "descriptor_tables/tss.h" 14 | #include "string.h" 15 | 16 | /// @brief The kernel 17 | /// 18 | static tss_entry_t kernel_tss; 19 | 20 | void tss_init(uint8_t idx, uint32_t ss0) 21 | { 22 | uint32_t base = (uint32_t)&kernel_tss; 23 | uint32_t limit = base + sizeof(tss_entry_t); 24 | 25 | // Add the TSS descriptor to the GDT. 26 | // Kernel tss, access(E9 = 1 11 0 1 0 0 1) 27 | // 1 present 28 | // 11 ring 3 (kernel) 29 | // 0 always 0 when dealing with system segments 30 | // 1 execution 31 | // 0 can not be executed by ring lower or equal to DPL, 32 | // 0 not readable 33 | // 1 access bit, always 0, cpu set this to 1 when accessing this sector 34 | gdt_set_gate(idx, base, limit, GDT_PRESENT | GDT_USER | GDT_EX | GDT_AC, 0x0); 35 | 36 | // Note that we usually set tss's esp to 0 when booting our os, however, 37 | // we need to set it to the real esp when we've switched to usermode 38 | // because the CPU needs to know what esp to use when usermode app is 39 | // calling a kernel function(aka system call), that's why we have a 40 | // function below called tss_set_stack. 41 | memset(&kernel_tss, 0x0, sizeof(tss_entry_t)); 42 | kernel_tss.ss0 = ss0; 43 | kernel_tss.esp0 = 0x0; 44 | kernel_tss.cs = 0x0b; 45 | kernel_tss.ds = 0x13; 46 | kernel_tss.es = 0x13; 47 | kernel_tss.fs = 0x13; 48 | kernel_tss.gs = 0x13; 49 | kernel_tss.ss = 0x13; 50 | kernel_tss.iomap = sizeof(tss_entry_t); 51 | } 52 | 53 | void tss_set_stack(uint32_t kss, uint32_t kesp) 54 | { 55 | // Kernel data segment. 56 | kernel_tss.ss0 = kss; 57 | // Kernel stack address. 58 | kernel_tss.esp0 = kesp; 59 | } 60 | -------------------------------------------------------------------------------- /mentos/src/fs/fcntl.c: -------------------------------------------------------------------------------- 1 | /// @file fcntl.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "fs/vfs.h" 8 | #include "process/scheduler.h" 9 | #include "system/syscall.h" 10 | 11 | long sys_fcntl(int fd, unsigned int request, unsigned long data) 12 | { 13 | // Get the current task. 14 | task_struct *task = scheduler_get_current_process(); 15 | 16 | // Check the current FD. 17 | if (fd < 0 || fd >= task->max_fd) { 18 | return -EMFILE; 19 | } 20 | 21 | // Get the file descriptor. 22 | vfs_file_descriptor_t *vfd = &task->fd_list[fd]; 23 | 24 | // Verify that the file exists. 25 | vfs_file_t *file = vfd->file_struct; 26 | if (file == NULL) { 27 | return -ENOSYS; 28 | } 29 | 30 | // Perform the ioctl operation. 31 | return vfs_fcntl(file, request, data); 32 | } 33 | -------------------------------------------------------------------------------- /mentos/src/fs/ioctl.c: -------------------------------------------------------------------------------- 1 | /// @file ioctl.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "fs/vfs.h" 8 | #include "process/scheduler.h" 9 | #include "stdio.h" 10 | #include "system/printk.h" 11 | 12 | long sys_ioctl(int fd, unsigned int request, unsigned long data) 13 | { 14 | // Get the current task. 15 | task_struct *task = scheduler_get_current_process(); 16 | 17 | // Check the current FD. 18 | if (fd < 0 || fd >= task->max_fd) { 19 | return -EMFILE; 20 | } 21 | 22 | // Get the file descriptor. 23 | vfs_file_descriptor_t *vfd = &task->fd_list[fd]; 24 | 25 | // Verify that the file exists. 26 | vfs_file_t *file = vfd->file_struct; 27 | if (file == NULL) { 28 | return -ENOSYS; 29 | } 30 | 31 | // Perform the ioctl operation. 32 | return vfs_ioctl(file, request, data); 33 | } 34 | -------------------------------------------------------------------------------- /mentos/src/fs/open.c: -------------------------------------------------------------------------------- 1 | /// @file open.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "fcntl.h" 8 | #include "fs/vfs.h" 9 | #include "io/debug.h" 10 | #include "limits.h" 11 | #include "process/process.h" 12 | #include "process/scheduler.h" 13 | #include "stdio.h" 14 | #include "string.h" 15 | #include "system/printk.h" 16 | #include "system/syscall.h" 17 | 18 | int sys_open(const char *pathname, int flags, mode_t mode) 19 | { 20 | // Get the current task. 21 | task_struct *task = scheduler_get_current_process(); 22 | 23 | // Search for an unused fd. 24 | int fd = get_unused_fd(); 25 | if (fd < 0) { 26 | return fd; 27 | } 28 | 29 | // Try to open the file. 30 | vfs_file_t *file = vfs_open(pathname, flags, mode); 31 | if (file == NULL) { 32 | return -errno; 33 | } 34 | 35 | // Set the file descriptor id. 36 | task->fd_list[fd].file_struct = file; 37 | 38 | if (!bitmask_check(flags, O_APPEND)) { 39 | // Reset the offset. 40 | task->fd_list[fd].file_struct->f_pos = 0; 41 | } else { 42 | stat_t stat; 43 | // Stat the file. 44 | file->fs_operations->stat_f(file, &stat); 45 | // Point at the last character 46 | task->fd_list[fd].file_struct->f_pos = stat.st_size; 47 | } 48 | 49 | // Set the flags. 50 | task->fd_list[fd].flags_mask = flags; 51 | 52 | // Return the file descriptor and increment it. 53 | return fd; 54 | } 55 | 56 | int sys_close(int fd) 57 | { 58 | // Get the current task. 59 | task_struct *task = scheduler_get_current_process(); 60 | 61 | // Check the current FD. 62 | if (fd < 0 || fd >= task->max_fd) { 63 | return -EMFILE; 64 | } 65 | 66 | // Get the file. 67 | vfs_file_t *file = task->fd_list[fd].file_struct; 68 | if (file == NULL) { 69 | return -1; 70 | } 71 | 72 | // Remove the reference to the file. 73 | task->fd_list[fd].file_struct = NULL; 74 | 75 | // Call the close function. 76 | return vfs_close(file); 77 | } 78 | -------------------------------------------------------------------------------- /mentos/src/fs/readdir.c: -------------------------------------------------------------------------------- 1 | /// @file readdir.c 2 | /// @brief Function for accessing directory entries. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "assert.h" 7 | #include "dirent.h" 8 | #include "errno.h" 9 | #include "fs/vfs.h" 10 | #include "process/scheduler.h" 11 | #include "stdio.h" 12 | #include "string.h" 13 | #include "system/printk.h" 14 | #include "system/syscall.h" 15 | 16 | ssize_t sys_getdents(int fd, dirent_t *dirp, unsigned int count) 17 | { 18 | if (dirp == NULL) { 19 | printf("getdents: cannot read directory :" 20 | "Directory pointer is not valid\n"); 21 | return 0; 22 | } 23 | // Get the current process. 24 | task_struct *current_process = scheduler_get_current_process(); 25 | // Check the current task. 26 | assert(current_process && "There is no current process!"); 27 | // Check the current FD. 28 | if ((fd < 0) || (fd >= current_process->max_fd)) { 29 | return -EMFILE; 30 | } 31 | // Get the process-specific file descriptor. 32 | vfs_file_descriptor_t *process_fd = ¤t_process->fd_list[fd]; 33 | #if 0 34 | // Check the permissions. 35 | if (!(current_process->fd_list[fd].flags_mask & O_RDONLY)) { 36 | return -EROFS; 37 | } 38 | #endif 39 | // Get the associated file. 40 | vfs_file_t *file = process_fd->file_struct; 41 | if (file == NULL) { 42 | return -ENOSYS; 43 | } 44 | // Perform the read. 45 | ssize_t actual_read = vfs_getdents(file, dirp, process_fd->file_struct->f_pos, count); 46 | // Update the offset, only if the value the function returns is positive. 47 | if (actual_read > 0) { 48 | process_fd->file_struct->f_pos += actual_read; 49 | } 50 | return actual_read; 51 | } 52 | -------------------------------------------------------------------------------- /mentos/src/fs/stat.c: -------------------------------------------------------------------------------- 1 | /// @file stat.c 2 | /// @brief Stat functions. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "fs/vfs.h" 8 | #include "io/debug.h" 9 | #include "limits.h" 10 | #include "process/scheduler.h" 11 | #include "stdio.h" 12 | #include "string.h" 13 | 14 | int sys_stat(const char *path, stat_t *buf) { return vfs_stat(path, buf); } 15 | 16 | int sys_fstat(int fd, stat_t *buf) 17 | { 18 | // Get the current task. 19 | task_struct *task = scheduler_get_current_process(); 20 | 21 | // Check the current FD. 22 | if (fd < 0 || fd >= task->max_fd) { 23 | return -EMFILE; 24 | } 25 | 26 | // Get the file descriptor. 27 | vfs_file_descriptor_t *vfd = &task->fd_list[fd]; 28 | 29 | // Check the permissions. 30 | #if 0 31 | if (!(vfd->flags_mask & O_RDONLY)) { 32 | return -EROFS; 33 | } 34 | #endif 35 | 36 | // Check the file. 37 | if (vfd->file_struct == NULL) { 38 | return -ENOSYS; 39 | } 40 | 41 | return vfs_fstat(vfd->file_struct, buf); 42 | } 43 | -------------------------------------------------------------------------------- /mentos/src/io/mm_io.c: -------------------------------------------------------------------------------- 1 | /// @file mm_io.c 2 | /// @brief Memory Mapped IO functions implementation. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "io/mm_io.h" 7 | 8 | uint8_t in_memb(uint32_t addr) { return *((uint8_t *)(addr)); } 9 | 10 | uint16_t in_mems(uint32_t addr) { return *((uint16_t *)(addr)); } 11 | 12 | uint32_t in_meml(uint32_t addr) { return *((uint32_t *)(addr)); } 13 | 14 | void out_memb(uint32_t addr, uint8_t value) { (*((uint8_t *)(addr))) = (value); } 15 | 16 | void out_mems(uint32_t addr, uint16_t value) { (*((uint16_t *)(addr))) = (value); } 17 | 18 | void out_meml(uint32_t addr, uint32_t value) { (*((uint32_t *)(addr))) = (value); } 19 | -------------------------------------------------------------------------------- /mentos/src/kernel/sys.c: -------------------------------------------------------------------------------- 1 | /// @file sys.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "klib/mutex.h" 8 | #include "klib/stdatomic.h" 9 | #include "stdio.h" 10 | #include "sys/reboot.h" 11 | 12 | /// @brief Powers off the machine. 13 | static void machine_power_off(void) 14 | { 15 | while (1) { 16 | cpu_relax(); 17 | } 18 | } 19 | 20 | /// @brief Shutdown everything and perform a clean system power_off. 21 | static void kernel_power_off(void) 22 | { 23 | // kernel_shutdown_prepare(SYSTEM_POWER_OFF); 24 | // if (pm_power_off_prepare) 25 | // { 26 | // pm_power_off_prepare(); 27 | // } 28 | // migrate_to_reboot_cpu(); 29 | // syscore_shutdown(); 30 | printf("Power down\n"); 31 | // kmsg_dump(KMSG_DUMP_POWEROFF); 32 | machine_power_off(); 33 | } 34 | 35 | int sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg) 36 | { 37 | static mutex_t reboot_mutex; 38 | 39 | // For safety, we require "magic" arguments. 40 | if (magic1 != LINUX_REBOOT_MAGIC1 || (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A && 41 | magic2 != LINUX_REBOOT_MAGIC2B && magic2 != LINUX_REBOOT_MAGIC2C)) { 42 | return -EINVAL; 43 | } 44 | 45 | mutex_lock(&reboot_mutex, 0); 46 | 47 | switch (cmd) { 48 | case LINUX_REBOOT_CMD_RESTART: 49 | break; 50 | case LINUX_REBOOT_CMD_CAD_ON: 51 | break; 52 | case LINUX_REBOOT_CMD_CAD_OFF: 53 | break; 54 | case LINUX_REBOOT_CMD_HALT: 55 | break; 56 | case LINUX_REBOOT_CMD_POWER_OFF: 57 | kernel_power_off(); 58 | break; 59 | case LINUX_REBOOT_CMD_RESTART2: 60 | break; 61 | case LINUX_REBOOT_CMD_KEXEC: 62 | break; 63 | case LINUX_REBOOT_CMD_SW_SUSPEND: 64 | break; 65 | default: 66 | return -EINVAL; 67 | } 68 | mutex_unlock(&reboot_mutex); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /mentos/src/klib/assert.c: -------------------------------------------------------------------------------- 1 | /// @file assert.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "assert.h" 7 | #include "stdio.h" 8 | #include "system/panic.h" 9 | 10 | // Setup the logging for this file (do this before any other include). 11 | #include "sys/kernel_levels.h" // Include kernel log levels. 12 | #define __DEBUG_HEADER__ "[ASSERT]" ///< Change header. 13 | #define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. 14 | #include "io/debug.h" // Include debugging functions. 15 | 16 | void __assert_fail(const char *assertion, const char *file, const char *function, unsigned int line) 17 | { 18 | pr_emerg( 19 | "\n=== ASSERTION FAILED ===\n" 20 | "Assertion: %s\n" 21 | "Location : %s:%d\n" 22 | "Function : %s\n\n", 23 | assertion, file, line, (function ? function : "Unknown function")); 24 | kernel_panic("Assertion failed."); 25 | } 26 | -------------------------------------------------------------------------------- /mentos/src/klib/ctype.c: -------------------------------------------------------------------------------- 1 | /// @file ctype.c 2 | /// @brief Functions related to character handling. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "ctype.h" 7 | 8 | /// Distance from a uppercase character to the correspondent lowercase in ASCII. 9 | #define OFFSET 32 10 | 11 | int isdigit(int c) { return (c >= 48 && c <= 57); } 12 | 13 | int isalpha(int c) { return ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)); } 14 | 15 | int iscntrl(int c) { return ((c >= 0x00 && c <= 0x1F) || (c == 0x7F)); } 16 | 17 | int isalnum(int c) { return (isalpha(c) || isdigit(c)); } 18 | 19 | int isxdigit(int c) { return (isdigit(c) || (c >= 65 && c <= 70)); } 20 | 21 | int islower(int c) { return (c >= 97 && c <= 122); } 22 | 23 | int isupper(int c) { return (c >= 65 && c <= 90); } 24 | 25 | int tolower(int c) 26 | { 27 | if (isalpha(c) == 0 || islower(c)) { 28 | return c; 29 | } 30 | 31 | return c + OFFSET; 32 | } 33 | 34 | int toupper(int c) 35 | { 36 | if (isalpha(c) == 0 || isupper(c)) { 37 | return c; 38 | } 39 | 40 | return c - OFFSET; 41 | } 42 | 43 | int isspace(int c) { return (c == ' '); } 44 | -------------------------------------------------------------------------------- /mentos/src/klib/libgen.c: -------------------------------------------------------------------------------- 1 | /// @file libgen.c 2 | /// @brief String routines. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "libgen.h" 7 | #include "assert.h" 8 | #include "io/debug.h" 9 | #include "limits.h" 10 | #include "mem/paging.h" 11 | #include "string.h" 12 | #include "system/syscall.h" 13 | 14 | int dirname(const char *path, char *buffer, size_t buflen) 15 | { 16 | if ((path == NULL) || (buffer == NULL) || (buflen == 0)) { 17 | return 0; 18 | } 19 | // Search for the last slash. 20 | const char *last_slash = NULL; 21 | for (const char *it = path; *it; it++) { 22 | if ((*it) == '/') { 23 | last_slash = it; 24 | } 25 | } 26 | // If we were able to find a slash, and the slash is not in the first 27 | // position, copy the substring. 28 | if (last_slash) { 29 | // Get the length of the substring, if the last slash is at the beginning, 30 | // add 1. 31 | size_t dirlen = last_slash - path + (last_slash == path); 32 | // Check if the path will fit inside the buffer. 33 | if (dirlen >= buflen) { 34 | return 0; 35 | } 36 | // Copy the substring. 37 | strncpy(buffer, path, dirlen); 38 | // Close the buffer. 39 | buffer[dirlen] = 0; 40 | } else { 41 | strcpy(buffer, "."); 42 | } 43 | return 1; 44 | } 45 | 46 | const char *basename(const char *path) 47 | { 48 | // Search for the last slash. 49 | const char *last_slash = NULL; 50 | for (const char *it = path; *it; it++) { 51 | if ((*it) == '/') { 52 | last_slash = it; 53 | } 54 | } 55 | return last_slash ? last_slash + 1 : path; 56 | } 57 | -------------------------------------------------------------------------------- /mentos/src/klib/mutex.c: -------------------------------------------------------------------------------- 1 | /// @file mutex.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "klib/mutex.h" 7 | #include "io/debug.h" 8 | 9 | void mutex_lock(mutex_t *mutex, uint32_t owner) 10 | { 11 | pr_debug("[%d] Trying to lock mutex...\n", owner); 12 | int failure = 1; 13 | 14 | while (mutex->state == 0 || failure || mutex->owner != owner) { 15 | failure = 1; 16 | if (mutex->state == 0) { 17 | __asm__ __volatile__("movl $0x01,%%eax\n\t" // move 1 to eax 18 | "xchg %%eax,%0\n\t" // try to set the lock bit 19 | "mov %%eax,%1\n\t" // export our result to a test var 20 | : "=m"(mutex->state), "=r"(failure) 21 | : "m"(mutex->state) 22 | : "%eax"); 23 | } 24 | if (failure == 0) { 25 | mutex->owner = owner; //test to see if we got the lock bit 26 | } 27 | } 28 | } 29 | 30 | void mutex_unlock(mutex_t *mutex) { mutex->state = 0; } 31 | -------------------------------------------------------------------------------- /mentos/src/klib/spinlock.c: -------------------------------------------------------------------------------- 1 | /// @file spinlock.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "klib/spinlock.h" 7 | 8 | void spinlock_init(spinlock_t *spinlock) { (*spinlock) = SPINLOCK_FREE; } 9 | 10 | void spinlock_lock(spinlock_t *spinlock) 11 | { 12 | while (1) { 13 | if (atomic_set_and_test(spinlock, SPINLOCK_BUSY) == 0) { 14 | break; 15 | } 16 | while (*spinlock) { 17 | cpu_relax(); 18 | } 19 | } 20 | } 21 | 22 | void spinlock_unlock(spinlock_t *spinlock) 23 | { 24 | barrier(); 25 | atomic_set(spinlock, SPINLOCK_FREE); 26 | } 27 | 28 | int spinlock_trylock(spinlock_t *spinlock) { return atomic_set_and_test(spinlock, SPINLOCK_BUSY) == 0; } 29 | -------------------------------------------------------------------------------- /mentos/src/klib/stdlib.c: -------------------------------------------------------------------------------- 1 | /// @file stdlib.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "stdlib.h" 7 | 8 | /// Seed used to generate random numbers. 9 | static unsigned rseed = 0; 10 | 11 | void srand(unsigned x) { rseed = x; } 12 | 13 | unsigned rand(void) { return rseed = (rseed * 1103515245U + 12345U) & RAND_MAX; } 14 | 15 | float randf(void) { return ((float)rand() / (float)(RAND_MAX)); } 16 | 17 | int randint(int lb, int ub) { return lb + (rand() % (ub - lb + 1)); } 18 | 19 | unsigned randuint(unsigned lb, unsigned ub) { return lb + (rand() % (ub - lb + 1)); } 20 | 21 | float randfloat(float lb, float ub) { return lb + (randf() * (ub - lb)); } 22 | -------------------------------------------------------------------------------- /mentos/src/process/pid_manager.c: -------------------------------------------------------------------------------- 1 | /// @file pid_manager.c 2 | /// @brief Manages the PIDs in the system. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "process/pid_manager.h" 7 | #include "process/scheduler.h" 8 | #include "stdint.h" 9 | #include "string.h" 10 | 11 | /// Defines the size of the bitmap that keeps track of used PIDs. 12 | #define BITMAP_SIZE (MAX_PROCESSES / 32) 13 | 14 | /// Bitmap for tracking used PIDs. 15 | static uint32_t pid_bitmap[BITMAP_SIZE] = {0}; 16 | 17 | /// Keeps track of the last allocated PID. 18 | static pid_t last_pid = 1; 19 | 20 | void pid_manager_init(void) { memset(pid_bitmap, 0, sizeof(pid_bitmap)); } 21 | 22 | void pid_manager_mark_used(pid_t pid) { pid_bitmap[pid / 32] |= (1 << (pid % 32)); } 23 | 24 | void pid_manager_mark_free(pid_t pid) { pid_bitmap[pid / 32] &= ~(1 << (pid % 32)); } 25 | 26 | pid_t pid_manager_get_free_pid(void) 27 | { 28 | // Start searching from the next PID after the last allocated one. 29 | for (size_t offset = 0; offset < BITMAP_SIZE * 32; offset++) { 30 | // Calculate the current PID index with wrap-around. 31 | pid_t current_pid = (last_pid + offset) % (BITMAP_SIZE * 32); 32 | 33 | // Ensure PID 0 is skipped. 34 | if (current_pid == 0) { 35 | continue; 36 | } 37 | 38 | // Check the bitmap for availability. 39 | size_t i = current_pid / 32; // Index in the bitmap array. 40 | size_t j = current_pid % 32; // Bit position in the bitmap element. 41 | 42 | if ((pid_bitmap[i] & (1 << j)) == 0) { 43 | // Mark the PID as used. 44 | pid_manager_mark_used(current_pid); 45 | 46 | // Update the last allocated PID. 47 | last_pid = current_pid + 1; 48 | 49 | // Return the allocated PID. 50 | return current_pid; 51 | } 52 | } 53 | // No free PID found. 54 | return -1; 55 | } 56 | -------------------------------------------------------------------------------- /mentos/src/sys/utsname.c: -------------------------------------------------------------------------------- 1 | /// @file utsname.c 2 | /// @brief Functions used to provide information about the machine & OS. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | // Setup the logging for this file (do this before any other include). 7 | #include "sys/kernel_levels.h" // Include kernel log levels. 8 | #define __DEBUG_HEADER__ "[UTSNAM]" ///< Change header. 9 | #define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. 10 | #include "io/debug.h" // Include debugging functions. 11 | 12 | #include "errno.h" 13 | #include "fcntl.h" 14 | #include "fs/vfs.h" 15 | #include "string.h" 16 | #include "sys/utsname.h" 17 | #include "version.h" 18 | 19 | /// @brief Returns the hostname. 20 | /// @param name where the hostname is stored. 21 | /// @param len the length of the buffer. 22 | /// @return 0 on success, a negative value on failure. 23 | static inline int __gethostname(char *name, size_t len) 24 | { 25 | // Check if name is an invalid address. 26 | if (!name) { 27 | return -EFAULT; 28 | } 29 | // Check if len is negative. 30 | if (len < 0) { 31 | return -EINVAL; 32 | } 33 | // Open the file. 34 | vfs_file_t *file = vfs_open("/etc/hostname", O_RDONLY, 0); 35 | if (file == NULL) { 36 | pr_err("Cannot find `/etc/hostname`.\n"); 37 | return -ENOENT; 38 | } 39 | // Clear the buffer. 40 | memset(name, 0, len); 41 | // Read the content of the file. 42 | ssize_t ret = vfs_read(file, name, 0UL, len); 43 | if (ret < 0) { 44 | pr_err("Failed to read `/etc/hostname`.\n"); 45 | return ret; 46 | } 47 | // Close the file. 48 | vfs_close(file); 49 | return 0; 50 | } 51 | 52 | int sys_uname(utsname_t *buf) 53 | { 54 | if (buf == NULL) { 55 | return -EFAULT; 56 | } 57 | // Uname code goes here. 58 | strcpy(buf->sysname, OS_NAME); 59 | strcpy(buf->version, OS_VERSION); 60 | strcpy(buf->release, OS_VERSION); 61 | strcpy(buf->machine, "i686"); 62 | int ret = __gethostname(buf->nodename, SYS_LEN); 63 | if (ret != 0) { 64 | return ret; 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /mentos/src/system/errno.c: -------------------------------------------------------------------------------- 1 | /// @file errno.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "errno.h" 7 | #include "process/scheduler.h" 8 | 9 | /// @brief Returns the error number for the current process. 10 | /// @return Pointer to the error number. 11 | int *__geterrno(void) 12 | { 13 | static int _errno = 0; 14 | task_struct *current_process = scheduler_get_current_process(); 15 | if (current_process == NULL) { 16 | return &_errno; 17 | } 18 | return ¤t_process->error_no; 19 | } 20 | -------------------------------------------------------------------------------- /mentos/src/system/panic.c: -------------------------------------------------------------------------------- 1 | /// @file panic.c 2 | /// @brief Functions used to manage kernel panic. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "system/panic.h" 7 | #include "io/debug.h" 8 | #include "io/port_io.h" 9 | 10 | /// Shutdown port for qemu. 11 | #define SHUTDOWN_PORT 0x604 12 | extern int runtests; 13 | 14 | void kernel_panic(const char *msg) 15 | { 16 | pr_emerg("\nPANIC:\n%s\n\nWelcome to Kernel Debugging Land...\n\n", msg); 17 | pr_emerg("\n"); 18 | __asm__ __volatile__("cli"); // Disable interrupts 19 | if (runtests) { 20 | outports(SHUTDOWN_PORT, 0x2000); 21 | } // Terminate qemu running the tests 22 | for (;;) { 23 | // Decrease power consumption with hlt. 24 | __asm__ __volatile__("hlt"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /mentos/src/system/printk.c: -------------------------------------------------------------------------------- 1 | /// @file printk.c 2 | /// @brief Functions for managing the kernel messages. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "system/printk.h" 7 | #include "io/debug.h" 8 | 9 | void sys_syslog(const char *file, const char *fun, int line, short log_level, const char *format) 10 | { 11 | dbg_printf(file, fun, line, "[SYSLOG]", log_level, format); 12 | } 13 | -------------------------------------------------------------------------------- /programs/cat.c: -------------------------------------------------------------------------------- 1 | /// @file cat.c 2 | /// @brief `cat` program. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include "stddef.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char **argv) 16 | { 17 | if (argc < 2) { 18 | printf("cat: missing operand.\n"); 19 | printf("Try 'cat --help' for more information.\n"); 20 | return 1; 21 | } 22 | // Check if `--help` is provided. 23 | for (int i = 1; i < argc; ++i) { 24 | if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) { 25 | printf("Print the content of each given file.\n"); 26 | printf("Usage:\n"); 27 | printf(" cat \n"); 28 | return 0; 29 | } 30 | } 31 | int ret = 0; 32 | int fd; 33 | // Prepare the buffer for reading. 34 | char buffer[BUFSIZ]; 35 | // Iterate the arguments. 36 | for (int i = 1; i < argc; ++i) { 37 | // Initialize the file path. 38 | char *filepath = argv[i]; 39 | 40 | fd = open(filepath, O_RDONLY, 0); 41 | if (fd < 0) { 42 | printf("cat: %s: %s\n", filepath, strerror(errno)); 43 | ret = EXIT_FAILURE; 44 | continue; 45 | } 46 | ssize_t bytes_read = 0; 47 | // Put on the standard output the characters. 48 | while ((bytes_read = read(fd, buffer, BUFSIZ)) > 0) { 49 | write(STDOUT_FILENO, buffer, bytes_read); 50 | } 51 | close(fd); 52 | if (bytes_read < 0) { 53 | printf("%s: %s: %s\n", argv[0], filepath, strerror(errno)); 54 | ret = EXIT_FAILURE; 55 | } 56 | } 57 | return ret; 58 | } 59 | -------------------------------------------------------------------------------- /programs/chmod.c: -------------------------------------------------------------------------------- 1 | /// @file chmod.c 2 | /// @brief change file permissions 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | mode_t mode = 0; 17 | char *endptr; 18 | gid_t gid = -1; 19 | 20 | if (argc != 3) { 21 | fprintf(STDERR_FILENO, "%s: MODE FILE\n", argv[0]); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | mode = strtol(argv[1], &endptr, 8); 26 | if (*endptr != '\0') { 27 | fprintf(STDERR_FILENO, "%s: invalid mode: '%s'\n", argv[0], argv[1]); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | if (chmod(argv[2], mode) == -1) { 32 | fprintf(STDERR_FILENO, "%s: changing permissions of %s: %s\n", argv[0], argv[2], strerror(errno)); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | exit(EXIT_SUCCESS); 37 | } 38 | -------------------------------------------------------------------------------- /programs/chown.c: -------------------------------------------------------------------------------- 1 | /// @file chown.c 2 | /// @brief change file ownership 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | char *idptr; 18 | char *saveptr; 19 | char *endptr; 20 | uid_t uid = -1; 21 | gid_t gid = -1; 22 | passwd_t *pwd; 23 | group_t *grp; 24 | 25 | if (argc != 3) { 26 | fprintf(STDERR_FILENO, "%s: [OWNER][:[GROUP]] FILE\n", argv[0]); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | idptr = strtok_r(argv[1], ":", &saveptr); 31 | if (argv[1][0] != ':') { /* Skip the username */ 32 | uid = strtol(idptr, &endptr, 10); /* Allow a numeric string */ 33 | if (*endptr != '\0') { /* Was not pure numeric string */ 34 | pwd = getpwnam(idptr); /* Try getting UID for username */ 35 | if (pwd == NULL) { 36 | fprintf(STDERR_FILENO, "%s: invalid user: %s\n", argv[0], idptr); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | uid = pwd->pw_uid; 41 | } 42 | idptr = strtok_r(NULL, ":", &saveptr); 43 | } 44 | 45 | if (idptr != NULL) { 46 | gid = strtol(idptr, &endptr, 10); /* Allow a numeric string */ 47 | if (*endptr != '\0') { /* Was not pure numeric string */ 48 | grp = getgrnam(idptr); /* Try getting GID for groupname */ 49 | if (grp == NULL) { 50 | fprintf(STDERR_FILENO, "%s: invalid group: %s\n", argv[0], idptr); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | gid = grp->gr_gid; 55 | } 56 | } 57 | 58 | if (chown(argv[2], uid, gid) == -1) { 59 | fprintf(STDERR_FILENO, "%s: changing ownership of %s: %s\n", argv[0], argv[2], strerror(errno)); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | exit(EXIT_SUCCESS); 64 | } 65 | -------------------------------------------------------------------------------- /programs/clear.c: -------------------------------------------------------------------------------- 1 | /// @file clear.c 2 | /// @brief `clear` program. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | 8 | int main(int argc, char **argv) 9 | { 10 | puts("\033[J"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /programs/cp.c: -------------------------------------------------------------------------------- 1 | /// @file cp.c 2 | /// @brief `cp` program. 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char **argv) 17 | { 18 | if (argc < 3) { 19 | printf("%s: missing file operand.\n", argv[0]); 20 | printf("Try 'cp --help' for more information.\n"); 21 | return EXIT_FAILURE; 22 | } 23 | // Check if `--help` is provided. 24 | for (int i = 1; i < argc; ++i) { 25 | if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) { 26 | printf("%s - copy files\n", argv[0]); 27 | printf("Usage: %s SOURCE DEST\n", argv[0]); 28 | return EXIT_SUCCESS; 29 | } 30 | } 31 | // Prepare the buffer for reading. 32 | ssize_t bytes_read = 0; 33 | char buffer[BUFSIZ]; 34 | char *src = argv[1]; 35 | char *dest = argv[2]; 36 | 37 | int srcfd = open(src, O_RDONLY, 0); 38 | if (srcfd < 0) { 39 | err(EXIT_FAILURE, "%s: %s", argv[0], src); 40 | } 41 | 42 | int destfd = creat(dest, 0600); 43 | if (destfd < 0) { 44 | err(EXIT_FAILURE, "%s: %s", argv[0], dest); 45 | } 46 | 47 | // Write the content read from srcfd to destfd 48 | while ((bytes_read = read(srcfd, buffer, sizeof(buffer))) > 0) { 49 | if (write(destfd, buffer, bytes_read) != bytes_read) { 50 | err(EXIT_FAILURE, "%s: %s", argv[0], dest); 51 | } 52 | } 53 | // Close the file descriptors. 54 | close(srcfd); 55 | close(destfd); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /programs/date.c: -------------------------------------------------------------------------------- 1 | /// @file date.c 2 | /// @brief `date` program. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) 10 | { 11 | time_t rawtime = time(NULL); 12 | printf("Seconds since 01/01/1970 : %ld\n", rawtime); 13 | tm_t *timeinfo = localtime(&rawtime); 14 | printf( 15 | "It's %2d:%2d:%2d, %d weekday, %02d/%02d/%4d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, 16 | timeinfo->tm_wday, timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /programs/echo.c: -------------------------------------------------------------------------------- 1 | /// @file echo.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | int newline = 1; 13 | int eflag = 0; 14 | char buffer[BUFSIZ]; 15 | char *buf = buffer; 16 | char *arg; 17 | 18 | // Iterate all the words. 19 | while ((arg = *++argv) != NULL) { 20 | if (arg[0] != '-') { 21 | break; 22 | } 23 | 24 | // parse the options string 25 | while (*arg++) { 26 | if (*arg == 'n') { 27 | newline = 0; 28 | } else if (*arg == 'e') { 29 | eflag = '\\'; 30 | } else { 31 | break; 32 | } 33 | } 34 | } 35 | 36 | // Iterate all remaining words. 37 | while ((arg = *argv) != NULL) { 38 | // We do not expand escape codes. 39 | if (!eflag) { 40 | puts(arg); 41 | goto next_word; 42 | } 43 | 44 | // Expand escape codes 45 | int c; 46 | while ((c = *arg++) != 0) { 47 | if (c != eflag) { 48 | *buf++ = c; 49 | } else { 50 | switch (*arg) { 51 | case 'n': 52 | *buf++ = '\n'; 53 | break; 54 | default: 55 | *buf++ = *(arg - 1); 56 | *buf++ = *arg; 57 | } 58 | arg++; 59 | } 60 | } 61 | // null-terminate the current word 62 | *buf = 0; 63 | puts(buffer); 64 | 65 | next_word: 66 | // Add space if there are more words and the last word did not end with a new line 67 | if ((*(argv + 1) != NULL) && *(buf - 1) != '\n') { 68 | putchar(' '); 69 | } 70 | // reset buf pointer 71 | buf = buffer; 72 | argv++; 73 | } 74 | 75 | if (newline) { 76 | printf("\n"); 77 | } 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /programs/env.c: -------------------------------------------------------------------------------- 1 | /// @file env.c 2 | /// @brief `env` program. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | extern char **environ; 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | for (char **ep = environ; *ep; ++ep) { 14 | printf("%s\n", *ep); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /programs/false.c: -------------------------------------------------------------------------------- 1 | /// @file false.c 2 | /// @brief 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) { exit(1); } 10 | -------------------------------------------------------------------------------- /programs/id.c: -------------------------------------------------------------------------------- 1 | /// @file id.c 2 | /// @brief 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char **argv) 13 | { 14 | if (argc == 1) { 15 | uid_t uid = geteuid(); 16 | passwd_t *user = getpwuid(uid); 17 | gid_t gid = getegid(); 18 | group_t *grp = getgrgid(gid); 19 | 20 | printf("uid=%d(%s) gid=%d(%s)\n", uid, user->pw_name, gid, grp->gr_name); 21 | } else if (strncmp(argv[1], "--help", 6) == 0) { 22 | printf("Usage: %s [OPTION]\n", argv[0]); 23 | printf("Print user and group information\n"); 24 | printf(" -g, --group print only the effective group ID\n"); 25 | printf(" -u, --user print only the effective user ID\n"); 26 | printf(" --help display this help and exit\n"); 27 | } else if (strncmp(argv[1], "-u", 2) == 0 || strncmp(argv[1], "--user", 6) == 0) { 28 | printf("%d\n", geteuid()); 29 | } else if (strncmp(argv[1], "-g", 2) == 0 || strncmp(argv[1], "--group", 7) == 0) { 30 | printf("%d\n", getegid()); 31 | } else { 32 | printf("%s: invalid option '%s'\n", argv[0], argv[1]); 33 | printf("Try '%s --help' for more information\n", argv[0]); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /programs/init.c: -------------------------------------------------------------------------------- 1 | /// @file init.c 2 | /// @brief `init` program. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[], char *envp[]) 12 | { 13 | char *_argv[] = {"login", NULL}; 14 | int status; 15 | 16 | #pragma clang diagnostic push 17 | #pragma ide diagnostic ignored "EndlessLoop" 18 | while (1) { 19 | pid_t login = fork(); 20 | if (login == 0) { 21 | execv("/bin/login", _argv); 22 | printf("This is bad, I should not be here! EXEC NOT WORKING\n"); 23 | } 24 | 25 | while (wait(&status) != login) { 26 | } 27 | } 28 | #pragma clang diagnostic pop 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /programs/logo.c: -------------------------------------------------------------------------------- 1 | /// @file logo.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) 10 | { 11 | printf(" __ __ _ ___ ____ \n"); 12 | printf(" | \\/ | ___ _ __ | |_ / _ \\ / ___| \n"); 13 | printf(" | |\\/| | / _ \\ | '_ \\ | __| | | | | \\___ " 14 | "\\ \n"); 15 | printf(" | | | | | __/ | | | | | |_ | |_| | ___) |\n"); 16 | printf(" |_| |_| \\___| |_| |_| \\__| \\___/ |____/ \n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /programs/man.c: -------------------------------------------------------------------------------- 1 | /// @file man.c 2 | /// @brief Shows the available commands. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | if (argc == 1) { 17 | int fd = open("/bin", O_RDONLY | O_DIRECTORY, 0); 18 | if (fd == -1) { 19 | printf("%s: cannot access '/bin': %s\n", argv[0], strerror(errno)); 20 | return 1; 21 | } 22 | dirent_t dent; 23 | int per_line = 0; 24 | while (getdents(fd, &dent, sizeof(dirent_t)) == sizeof(dirent_t)) { 25 | // Shows only regular files 26 | if (dent.d_type == DT_REG) { 27 | printf("%10s ", dent.d_name); 28 | if (++per_line == 6) { 29 | per_line = 0; 30 | putchar('\n'); 31 | } 32 | } 33 | } 34 | putchar('\n'); 35 | close(fd); 36 | } else if (argc == 2) { 37 | char *pager = "more"; 38 | char filepath[PATH_MAX]; 39 | strcpy(filepath, "/usr/share/man/"); 40 | strncat(filepath, argv[1], PATH_MAX); 41 | strncat(filepath, ".man", PATH_MAX); 42 | int fd = open(filepath, O_RDONLY, 42); 43 | if (fd < 0) { 44 | printf("%s: No manual entry for %s\n", argv[0], argv[1]); 45 | exit(1); 46 | } 47 | close(fd); 48 | execlp(pager, pager, filepath, NULL); 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /programs/mkdir.c: -------------------------------------------------------------------------------- 1 | /// @file mkdir.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | // Check the number of arguments. 15 | if (argc != 2) { 16 | printf("%s: missing operand.\n", argv[0]); 17 | printf("Try '%s --help' for more information.\n", argv[0]); 18 | return 1; 19 | } 20 | if (strcmp(argv[1], "--help") == 0) { 21 | printf("Creates a new directory.\n"); 22 | printf("Usage:\n"); 23 | printf(" %s \n", argv[0]); 24 | return 0; 25 | } 26 | if (mkdir(argv[1], S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { 27 | printf("mkdir: cannot create directory '%s': %s\n", argv[1], strerror(errno)); 28 | } 29 | putchar('\n'); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /programs/nice.c: -------------------------------------------------------------------------------- 1 | /// @file nice.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | if (argc == 1) { 13 | int current = nice(0); 14 | printf("%d\n", current); 15 | return 0; 16 | } 17 | if (argc != 2) { 18 | printf("%s: missing operand.\n", argv[0]); 19 | printf("Try '%s --help' for more information.\n", argv[0]); 20 | return 1; 21 | } 22 | if (!strcmp(argv[1], "--help")) { 23 | printf("Usage: %s \n", argv[0]); 24 | return 0; 25 | } 26 | char *endptr; 27 | long increment = strtol(argv[1], &endptr, 10); 28 | if (*endptr != '\0' || increment < -40 || increment > 40) { 29 | printf("Error: You must provide a value between (-40,+40).\n"); 30 | return 1; 31 | } 32 | int newNice = nice(increment); 33 | printf("Your new nice value is %d.\n", newNice); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /programs/poweroff.c: -------------------------------------------------------------------------------- 1 | /// @file poweroff.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | printf("Executing power-off...\n"); 13 | reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /programs/pwd.c: -------------------------------------------------------------------------------- 1 | /// @file pwd.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | char cwd[PATH_MAX]; 13 | getcwd(cwd, PATH_MAX); 14 | printf("%s\n", cwd); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /programs/rmdir.c: -------------------------------------------------------------------------------- 1 | /// @file rmdir.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | // Check the number of arguments. 14 | if (argc != 2) { 15 | printf("Bad usage.\n"); 16 | printf("Try 'rmdir --help' for more information.\n"); 17 | return 1; 18 | } 19 | if (strcmp(argv[1], "--help") == 0) { 20 | printf("Removes a directory.\n"); 21 | printf("Usage:\n"); 22 | printf(" rmdir \n"); 23 | return 0; 24 | } 25 | if (rmdir(argv[1]) == -1) { 26 | printf("%s: failed to remove '%s': %s\n", argv[0], argv[1], strerror(errno)); 27 | return 1; 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /programs/showpid.c: -------------------------------------------------------------------------------- 1 | /// @file showpid.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) 10 | { 11 | printf("pid %d\n", getppid()); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /programs/sleep.c: -------------------------------------------------------------------------------- 1 | /// @file sleep.c 2 | /// @brief Simple sleep program that pauses for a specified number of seconds. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | // Check if an argument is provided 13 | if (argc == 2) { 14 | // Convert the argument to an integer 15 | char *endptr; 16 | long amount = strtol(argv[1], &endptr, 10); 17 | 18 | // Check for conversion errors 19 | if (*endptr != '\0' || amount <= 0 || amount > INT_MAX) { 20 | fprintf(stderr, "Error: Please enter a valid positive integer for sleep duration.\n"); 21 | return 1; 22 | } 23 | 24 | // Ensure the amount is positive 25 | if (amount > 0) { 26 | printf("Sleeping for %ld seconds...\n", amount); 27 | sleep(amount); 28 | printf("Awake after %ld seconds.\n", amount); 29 | } else { 30 | fprintf(stderr, "Error: Please enter a positive integer for sleep duration.\n"); 31 | return 1; 32 | } 33 | } else { 34 | fprintf(stderr, "Usage: %s \n", argv[0]); 35 | return 1; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /programs/tests/t_abort.c: -------------------------------------------------------------------------------- 1 | /// @file t_abort.c 2 | /// @brief Demonstrates handling of the SIGABRT signal. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | void sig_handler(int sig) 16 | { 17 | printf("handler(%d) : Starting handler.\n", sig); 18 | if (sig == SIGABRT) { 19 | static int counter = 0; 20 | counter += 1; 21 | 22 | printf("handler(%d) : Correct signal. ABRT (%d/3)\n", sig, counter); 23 | if (counter < 3) { 24 | // Re-trigger the abort signal up to 3 times. 25 | abort(); 26 | } else { 27 | // Exit the program after handling the signal 3 times. 28 | exit(EXIT_SUCCESS); 29 | } 30 | } else { 31 | printf("handler(%d) : Wrong signal.\n", sig); 32 | } 33 | printf("handler(%d) : Ending handler.\n", sig); 34 | } 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | sigaction_t action; 39 | memset(&action, 0, sizeof(action)); 40 | action.sa_handler = sig_handler; 41 | 42 | // Set up the signal handler for SIGABRT. 43 | if (sigaction(SIGABRT, &action, NULL) == -1) { 44 | perror("signal setup failed"); 45 | exit(EXIT_FAILURE); 46 | } 47 | 48 | // Trigger the SIGABRT signal. 49 | abort(); 50 | 51 | // This point should never be reached. 52 | perror("abort() failed to terminate the process"); 53 | 54 | return EXIT_FAILURE; 55 | } 56 | -------------------------------------------------------------------------------- /programs/tests/t_alarm.c: -------------------------------------------------------------------------------- 1 | /// @file t_alarm.c 2 | /// @brief Demonstrates handling of the SIGALRM signal. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /// @brief Signal handler for SIGALRM. 16 | /// @param sig The signal number. 17 | void alarm_handler(int sig) 18 | { 19 | printf("handler(%d) : Starting handler.\n", sig); 20 | if (sig == SIGALRM) { 21 | // Set an alarm to go off after 1 seconds. 22 | alarm(1); 23 | 24 | // Set another alarm to go off after 1 seconds and get the remaining time of the previous alarm. 25 | unsigned int rest = alarm(1); 26 | 27 | // Expected value: 1 (since the previous alarm was just set to 1 seconds). 28 | printf("handler(%d) : alarm(1) result: %d.\n", sig, rest); 29 | 30 | // Cancel the alarm and get the remaining time of the previous alarm. 31 | rest = alarm(0); 32 | 33 | // Expected value: ~4 (since the previous alarm was just set to 1 34 | // seconds again). This small delay between the two alarm calls is why 35 | // you see the value 4 instead of 1. The exact value can vary slightly 36 | // depending on the system’s execution speed and the time taken to 37 | // execute the intermediate code. 38 | printf("handler(%d) : alarm(0) result: %d.\n", sig, rest); 39 | 40 | exit(EXIT_SUCCESS); 41 | } else { 42 | printf("handler(%d) : Wrong signal.\n", sig); 43 | } 44 | printf("handler(%d) : Ending handler.\n", sig); 45 | } 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | sigaction_t action; 50 | memset(&action, 0, sizeof(action)); 51 | action.sa_handler = alarm_handler; 52 | 53 | // Set up the signal handler for SIGALRM. 54 | if (sigaction(SIGALRM, &action, NULL) < 0) { 55 | perror("signal setup failed"); 56 | exit(EXIT_FAILURE); 57 | } 58 | 59 | // Set an alarm to go off after 1 seconds. 60 | alarm(1); 61 | 62 | // Infinite loop to keep the program running until the alarm signal is received. 63 | while (1) { 64 | } 65 | 66 | return EXIT_SUCCESS; 67 | } 68 | -------------------------------------------------------------------------------- /programs/tests/t_chdir.c: -------------------------------------------------------------------------------- 1 | /// @file t_chdir.c 2 | /// @brief Test program for the chdir system call. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | const char *directory = "/home"; // Default directory if none is provided 14 | char cwd[1024]; 15 | 16 | // Try to change the current working directory. 17 | if (chdir(directory) == 0) { 18 | // Success, print the current working directory. 19 | if (getcwd(cwd, sizeof(cwd)) != NULL) { 20 | // Compare cwd and the expected directory. 21 | if (strcmp(cwd, directory) == 0) { 22 | printf("Successfully changed to the directory.\n"); 23 | return EXIT_SUCCESS; 24 | } 25 | printf( 26 | "Directory change failed or directory differs: expected %s " 27 | "but got %s\n", 28 | directory, cwd); 29 | 30 | } else { 31 | perror("getcwd failed"); 32 | } 33 | } else { 34 | perror("chdir failed"); 35 | } 36 | return EXIT_FAILURE; 37 | } 38 | -------------------------------------------------------------------------------- /programs/tests/t_environ.c: -------------------------------------------------------------------------------- 1 | /// @file t_getenv.c 2 | /// @brief Test the getenv function. 3 | /// @details This program tests the `getenv` function by retrieving the value of 4 | /// an environment variable and printing it. If the environment variable is not 5 | /// set, it prints an error message and exits with a failure status. 6 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 7 | /// See LICENSE.md for details. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | const char *env_var = "TEST_ENV"; 18 | const char *initial_value = "InitialValue"; 19 | const char *updated_value = "UpdatedValue"; 20 | 21 | // Set the environment variable 22 | if (setenv(env_var, initial_value, 1) != 0) { 23 | perror("setenv failed"); 24 | return EXIT_FAILURE; 25 | } 26 | 27 | // Retrieve the environment variable 28 | const char *value = getenv(env_var); 29 | if (!value) { 30 | fprintf(stderr, "getenv failed: Environment variable %s not found.\n", env_var); 31 | return EXIT_FAILURE; 32 | } 33 | 34 | // Verify the retrieved value matches the set value 35 | if (strcmp(value, initial_value) != 0) { 36 | fprintf(stderr, "Mismatch: Expected '%s', but got '%s'.\n", initial_value, value); 37 | return EXIT_FAILURE; 38 | } 39 | 40 | // Update the environment variable 41 | if (setenv(env_var, updated_value, 1) != 0) { 42 | perror("setenv failed (update)"); 43 | return EXIT_FAILURE; 44 | } 45 | 46 | // Retrieve the updated environment variable 47 | value = getenv(env_var); 48 | if (!value) { 49 | fprintf(stderr, "getenv failed: Environment variable %s not found after update.\n", env_var); 50 | return EXIT_FAILURE; 51 | } 52 | 53 | // Verify the retrieved value matches the updated value 54 | if (strcmp(value, updated_value) != 0) { 55 | fprintf(stderr, "Mismatch after update: Expected '%s', but got '%s'.\n", updated_value, value); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | // Print success message 60 | printf("Environment variable %s tested successfully.\n", env_var); 61 | 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /programs/tests/t_exec.c: -------------------------------------------------------------------------------- 1 | /// @file t_exec.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | pid_t pid; 15 | int status; 16 | 17 | // Fork a new process 18 | pid = fork(); 19 | 20 | if (pid < 0) { 21 | // Error in forking 22 | perror("fork"); 23 | return EXIT_FAILURE; 24 | } 25 | 26 | if (pid == 0) { 27 | // Child process: Use exec to replace the child process image 28 | 29 | // Program to execute: /bin/echo 30 | // Arguments: /bin/echo "Exec test successful" 31 | execl("/bin/echo", "echo", "Exec test successful", NULL); 32 | 33 | // If exec fails, print an error and exit 34 | perror("execl"); 35 | exit(EXIT_FAILURE); 36 | } else { 37 | // Parent process: Wait for the child process to complete 38 | if (waitpid(pid, &status, 0) == -1) { 39 | perror("waitpid"); 40 | return EXIT_FAILURE; 41 | } 42 | 43 | // Check if the child terminated successfully 44 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 45 | // exec worked 46 | return EXIT_SUCCESS; 47 | } // exec failed or child terminated abnormally 48 | return EXIT_FAILURE; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /programs/tests/t_exit.c: -------------------------------------------------------------------------------- 1 | /// @file t_exit.c 2 | /// @brief Test program for the exit system call. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | // Simple test to show successful exit. 12 | exit(EXIT_SUCCESS); 13 | 14 | // This code should not be reached. 15 | return EXIT_FAILURE; 16 | } 17 | -------------------------------------------------------------------------------- /programs/tests/t_fork.c: -------------------------------------------------------------------------------- 1 | /// @file t_fork.c 2 | /// @brief Test the fork syscall. 3 | /// @details This program tests the `fork` system call by creating child 4 | /// processes and having them execute in a loop until a specified number of 5 | /// processes is reached. Each process waits for its child to finish before 6 | /// exiting. 7 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 8 | /// See LICENSE.md for details. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | pid_t pid; 19 | 20 | // Fork a new process 21 | pid = fork(); 22 | 23 | if (pid < 0) { 24 | // Error in forking 25 | perror("fork"); 26 | return EXIT_FAILURE; 27 | } 28 | 29 | if (pid == 0) { 30 | // Child process 31 | printf("Child process: PID = %d, Parent PID = %d\n", getpid(), getppid()); 32 | // Simulate some work in the child 33 | sleep(1); 34 | printf("Child process exiting successfully.\n"); 35 | exit(EXIT_SUCCESS); 36 | } else { 37 | // Parent process 38 | printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid); 39 | 40 | // Wait for the child process to complete 41 | int status; 42 | if (waitpid(pid, &status, 0) == -1) { 43 | perror("waitpid"); 44 | return EXIT_FAILURE; 45 | } 46 | 47 | // Check if the child exited normally 48 | if (WIFEXITED(status)) { 49 | printf("Parent process: Child exited with status %d.\n", WEXITSTATUS(status)); 50 | return EXIT_SUCCESS; 51 | } 52 | printf("Parent process: Child did not exit normally.\n"); 53 | return EXIT_FAILURE; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /programs/tests/t_groups.c: -------------------------------------------------------------------------------- 1 | /// @file t_groups.c 2 | /// @brief Test process group and session IDs. 3 | /// @details This program tests the retrieval of process IDs, group IDs, and 4 | /// session IDs. It forks multiple child processes, each of which prints its own 5 | /// IDs and those of its parent. The parent process waits for all child 6 | /// processes to finish before exiting. This demonstrates the relationship 7 | /// between parent and child processes in terms of IDs. 8 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 9 | /// See LICENSE.md for details. 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | int main(int argc, char **argv) 18 | { 19 | // Get the group ID, process ID, and session ID of the current process. 20 | pid_t gid = getgid(); 21 | pid_t pid = getpid(); 22 | pid_t sid = getsid(0); 23 | 24 | // Print the IDs of the current process. 25 | printf("pid: %d, gid: %d, sid: %d\n\n", pid, gid, sid); 26 | 27 | // Fork 5 child processes. 28 | for (int i = 0; i < 5; ++i) { 29 | if (fork() == 0) { 30 | // In the child process, get the group ID, process ID, parent process ID, and session ID. 31 | pid_t gid_child = getgid(); 32 | pid_t pid_child = getpid(); 33 | pid_t ppid_child = getppid(); 34 | pid_t sid_child = getsid(ppid_child); 35 | 36 | // Request to sleep for (i * 100 ms). 37 | struct timespec req = {0, i * 100000000}; 38 | nanosleep(&req, NULL); 39 | 40 | // Print the IDs of the child process and its parent. 41 | printf( 42 | "%d) pid_child: %d, gid_child: %d, ppid_child: %d, sid_child: " 43 | "%d\n", 44 | i, pid_child, gid_child, ppid_child, sid_child); 45 | exit(EXIT_SUCCESS); 46 | } 47 | } 48 | 49 | // Wait for all child processes to finish. 50 | while (wait(NULL) != -1) { 51 | } 52 | 53 | return EXIT_SUCCESS; 54 | } 55 | -------------------------------------------------------------------------------- /programs/tests/t_grp.c: -------------------------------------------------------------------------------- 1 | /// @file t_pwd.c 2 | /// @brief Test the libc grp.h interface. 3 | /// @details This program tests the `getgrnam` and `getgrgid` functions from the 4 | /// libc `grp.h` interface. It verifies that the functions correctly handle both 5 | /// existing and non-existent group names and GIDs. If any test fails, the 6 | /// program exits with an error message and a failure status. 7 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 8 | /// See LICENSE.md for details. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /// @brief Test the getgrnam function. 19 | /// @details This function tests that `getgrnam` correctly handles both existing 20 | /// and non-existent group names. 21 | static void __test_getgrnam(void) 22 | { 23 | // Test that getgrnam returns NULL for a non-existent group name. 24 | if (getgrnam("r") != NULL) { 25 | errx(EXIT_FAILURE, "Group entry for non-existent group \"r\" found"); 26 | } 27 | 28 | // Test that getgrnam returns a valid entry for the "root" group. 29 | if (getgrnam("root") == NULL) { 30 | errx(EXIT_FAILURE, "Group entry for root group not found"); 31 | } 32 | } 33 | 34 | /// @brief Test the getgrgid function. 35 | /// @details This function tests that `getgrgid` correctly handles both existing 36 | /// and non-existent GIDs. 37 | static void __test_getgrgid(void) 38 | { 39 | // Test that getgrgid returns NULL for a non-existent GID. 40 | if (getgrgid(1337) != NULL) { 41 | errx(EXIT_FAILURE, "Group entry for non-existent gid 1337 found"); 42 | } 43 | 44 | // Test that getgrgid returns a valid entry for existing GIDs. 45 | int gids[] = {0, 1000}; 46 | for (int i = 0; i < sizeof(gids) / sizeof(int); i++) { 47 | if (getgrgid(gids[i]) == NULL) { 48 | errx(EXIT_FAILURE, "Group entry for gid %d not found", gids[i]); 49 | } 50 | } 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | // Test the getgrnam function. 56 | __test_getgrnam(); 57 | // Test the getgrgid function. 58 | __test_getgrgid(); 59 | 60 | return EXIT_SUCCESS; 61 | } 62 | -------------------------------------------------------------------------------- /programs/tests/t_periodic2.c: -------------------------------------------------------------------------------- 1 | /// @file t_periodic2.c 2 | /// @brief Test program for periodic scheduling. 3 | /// @details This program sets periodic scheduling parameters for the current process 4 | /// and periodically prints a counter. It demonstrates the use of `sched_getparam`, 5 | /// `sched_setparam`, and `waitperiod` functions for managing periodic tasks in a real-time system. 6 | /// The program runs until the counter reaches 10 or an error occurs in `waitperiod`. 7 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 8 | /// See LICENSE.md for details. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | pid_t cpid = getpid(); 19 | struct sched_param param; 20 | 21 | // Get current scheduling parameters. 22 | if (sched_getparam(cpid, ¶m) == -1) { 23 | fprintf(STDERR_FILENO, "Failed to get scheduling parameters: %s\n", strerror(errno)); 24 | return EXIT_FAILURE; 25 | } 26 | 27 | // Change scheduling parameters. 28 | param.sched_priority = 1; // Set priority (example value, adjust as needed). 29 | param.period = 4000; // Set period to 4000 ms. 30 | param.deadline = 4000; // Set deadline to 4000 ms. 31 | param.is_periodic = 1; // Set as periodic task. 32 | 33 | // Set modified scheduling parameters. 34 | if (sched_setparam(cpid, ¶m) == -1) { 35 | fprintf(STDERR_FILENO, "Failed to set scheduling parameters: %s\n", strerror(errno)); 36 | return EXIT_FAILURE; 37 | } 38 | 39 | int counter = 0; 40 | 41 | // Periodically print the counter. 42 | while (1) { 43 | if (++counter == 10) { 44 | break; 45 | } 46 | printf("[periodic2] counter: %d\n", counter); 47 | 48 | // Wait for the next period. 49 | if (waitperiod() == -1) { 50 | fprintf(STDERR_FILENO, "[%s] Error in waitperiod: %s\n", argv[0], strerror(errno)); 51 | break; 52 | } 53 | } 54 | 55 | return EXIT_SUCCESS; 56 | } 57 | -------------------------------------------------------------------------------- /programs/tests/t_scanf.c: -------------------------------------------------------------------------------- 1 | /// @file t_scanf.c 2 | /// @brief Test the scanf function. 3 | /// @copyright (c) 2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | 8 | int main(void) 9 | { 10 | int number; 11 | char name[100]; 12 | 13 | printf("Enter a number: "); 14 | if (scanf("%d", &number) != 1) { 15 | printf("Failed to read number.\n"); 16 | return 1; 17 | } 18 | 19 | printf("Enter your name: "); 20 | if (scanf("%99s", name) != 1) { // %99s to prevent buffer overflow 21 | printf("Failed to read name.\n"); 22 | return 1; 23 | } 24 | 25 | printf("Hello, %s! You entered %d.\n", name, number); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /programs/tests/t_shmget.c: -------------------------------------------------------------------------------- 1 | /// @file t_shmget.c 2 | /// @brief Demonstrates the creation and usage of shared memory between a parent 3 | /// and child process. 4 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 5 | /// See LICENSE.md for details. 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /// Define the size of shared memory to hold two integers. 16 | #define MEM_SIZE (sizeof(int) * 2) 17 | 18 | int main(void) 19 | { 20 | int shmid; 21 | pid_t cpid; 22 | int *array; 23 | 24 | // Create shared memory segment with IPC_PRIVATE key and specified memory size. 25 | shmid = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0600); 26 | if (shmid == -1) { 27 | perror("shmget"); 28 | return EXIT_FAILURE; 29 | } 30 | printf("shmid = %d;\n", shmid); 31 | 32 | // Create a child. 33 | cpid = fork(); 34 | if (cpid == 0) { 35 | // Child attaches the shared memory. 36 | array = (int *)shmat(shmid, NULL, 0); 37 | if (array == NULL) { 38 | perror("shmat"); 39 | return EXIT_FAILURE; 40 | } 41 | printf("C: %p\n", array); 42 | array[0] = 1; 43 | return 0; 44 | } 45 | 46 | // Father attaches the shared memory. 47 | array = (int *)shmat(shmid, NULL, 0); 48 | if (array == NULL) { 49 | perror("shmat"); 50 | return EXIT_FAILURE; 51 | } 52 | 53 | // Wait for the child to finish. 54 | while (wait(NULL) != -1) { 55 | } 56 | 57 | printf("F: %p\n", array); 58 | array[1] = 2; 59 | 60 | printf("array[%d] : %d\n", 0, array[0]); 61 | printf("array[%d] : %d\n", 1, array[1]); 62 | 63 | // Detatch the shared memory. 64 | if (shmdt(array) < 0) { 65 | perror("shmdt"); 66 | return EXIT_FAILURE; 67 | } 68 | 69 | // Remove the shared memory. 70 | if (shmctl(shmid, IPC_RMID, NULL) == -1) { 71 | perror("shmctl"); 72 | return EXIT_FAILURE; 73 | } 74 | return EXIT_SUCCESS; 75 | } 76 | -------------------------------------------------------------------------------- /programs/tests/t_sigfpe.c: -------------------------------------------------------------------------------- 1 | /// @file t_sigfpe.c 2 | /// @brief Demonstrates handling of a SIGFPE (floating-point exception) signal 3 | /// using sigaction. The program intentionally triggers a division by zero to 4 | /// cause the SIGFPE signal. 5 | /// @details 6 | /// This program sets a signal handler for the SIGFPE signal, which is raised 7 | /// when a floating-point exception occurs (in this case, division by zero). 8 | /// When the signal is received, the handler function is invoked, which catches 9 | /// the exception, displays relevant messages, and then exits. The program 10 | /// contains a section that deliberately divides by zero to trigger this signal. 11 | /// 12 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 13 | /// See LICENSE.md for details. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /// Signal handler function that catches and handles SIGFPE. 25 | void sig_handler(int sig) 26 | { 27 | printf("handler(%d) : Starting handler.\n", sig); 28 | if (sig == SIGFPE) { 29 | printf("handler(%d) : Correct signal. FPE\n", sig); 30 | printf("handler(%d) : Exiting\n", sig); 31 | exit(0); 32 | } else { 33 | printf("handler(%d) : Wrong signal.\n", sig); 34 | } 35 | printf("handler(%d) : Ending handler.\n", sig); 36 | } 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | sigaction_t action; 41 | memset(&action, 0, sizeof(action)); 42 | action.sa_handler = sig_handler; 43 | 44 | // Set the SIGUSR1 handler using sigaction. 45 | if (sigaction(SIGFPE, &action, NULL) == -1) { 46 | printf("Failed to set signal handler (%s).\n", strerror(errno)); 47 | return 1; 48 | } 49 | 50 | printf("Diving by zero (unrecoverable)...\n"); 51 | 52 | // Should trigger ALU error, fighting the compiler... 53 | int d = 1; 54 | int e = 1; 55 | d /= e; 56 | e -= 1; 57 | d /= e; 58 | e -= 1; 59 | printf("d: %d, e: %d\n", d, e); 60 | 61 | return EXIT_SUCCESS; 62 | } 63 | -------------------------------------------------------------------------------- /programs/tests/t_sleep.c: -------------------------------------------------------------------------------- 1 | /// @file t_sleep.c 2 | /// @brief Demonstrates the use of the sleep function to pause program execution 3 | /// for a specified duration. 4 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 5 | /// See LICENSE.md for details. 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | // Sleep for 500 ms. 19 | struct timespec req = {0, 500000000}; // 500 ms = 500,000,000 nanoseconds 20 | 21 | if (nanosleep(&req, NULL) != 0) { 22 | fprintf(stderr, "nanosleep error: %s\n", strerror(errno)); 23 | return EXIT_FAILURE; 24 | } 25 | 26 | return EXIT_SUCCESS; 27 | } 28 | -------------------------------------------------------------------------------- /programs/tests/t_syslog.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | // Open syslog connection with identifier "syslog_test" 7 | openlog("syslog_test", LOG_CONS | LOG_PID, LOG_USER); 8 | 9 | // Set log mask to allow only messages of priority LOG_WARNING and above 10 | setlogmask(LOG_UPTO(LOG_WARNING)); 11 | 12 | // Log messages at different levels to test filtering 13 | syslog(LOG_DEBUG, "This is a debug message and should not appear.\n"); 14 | syslog(LOG_INFO, "This is an info message and should not appear.\n"); 15 | syslog(LOG_NOTICE, "This is a notice message and should not appear.\n"); 16 | syslog(LOG_WARNING, "This is a warning message and should appear.\n"); 17 | syslog(LOG_ERR, "This is an error message and should appear.\n"); 18 | syslog(LOG_CRIT, "This is a critical message and should appear.\n"); 19 | syslog(LOG_ALERT, "This is an alert message and should appear.\n"); 20 | syslog(LOG_EMERG, "This is an emergency message and should appear.\n"); 21 | 22 | // Close the syslog connection 23 | closelog(); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /programs/tests/t_time.c: -------------------------------------------------------------------------------- 1 | /// @file t_time.c 2 | /// @brief Test program for the time() function. 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(void) 11 | { 12 | // Get the current time 13 | time_t current_time = time(NULL); 14 | 15 | // Check if the time function failed 16 | if (current_time == (time_t)-1) { 17 | perror("Error: time() failed"); 18 | return EXIT_FAILURE; 19 | } 20 | 21 | // Convert to local time and print the result 22 | char *time_str = ctime(¤t_time); 23 | if (time_str == NULL) { 24 | perror("Error: ctime() failed"); 25 | return EXIT_FAILURE; 26 | } 27 | 28 | printf("Current time is: `%s`\n", time_str); 29 | 30 | return EXIT_SUCCESS; 31 | } 32 | -------------------------------------------------------------------------------- /programs/touch.c: -------------------------------------------------------------------------------- 1 | /// @file touch.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char **argv) 15 | { 16 | if (argc != 2) { 17 | printf("%s: missing operand.\n", argv[0]); 18 | printf("Try '%s --help' for more information.\n", argv[0]); 19 | return 1; 20 | } 21 | if (strcmp(argv[1], "--help") == 0) { 22 | printf("Updates modification time or creates given file.\n "); 23 | printf("Usage:\n"); 24 | printf(" touch \n"); 25 | return 0; 26 | } 27 | int fd = open(argv[1], O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); 28 | if (fd < 0) { 29 | err(EXIT_FAILURE, "cannot touch %s", argv[1]); 30 | printf("\n"); 31 | } 32 | close(fd); 33 | printf("\n"); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /programs/uname.c: -------------------------------------------------------------------------------- 1 | /// @file uname.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char **argv) 11 | { 12 | utsname_t utsname; 13 | uname(&utsname); 14 | if (argc != 2) { 15 | printf("%s\n", utsname.sysname); 16 | return -1; 17 | } 18 | 19 | if (!(strcmp(argv[1], "-a")) || !(strcmp(argv[1], "--all")) || !(strcmp(argv[1], "-i")) || 20 | !(strcmp(argv[1], "--info"))) { 21 | printf("%s %s \n", utsname.sysname, utsname.version); 22 | } else if (!(strcmp(argv[1], "-r")) || !(strcmp(argv[1], "--rev"))) { 23 | printf("%s\n", utsname.version); 24 | } else if (!(strcmp(argv[1], "-i")) || !(strcmp(argv[1], "--info"))) { 25 | 26 | } else if (!(strcmp(argv[1], "-h")) || !(strcmp(argv[1], "--help"))) { 27 | printf("Uname function allow you to see the kernel and system " 28 | "information.\n"); 29 | printf("Function avaibles:\n"); 30 | printf("1) -a - Kernel version and processor type\n" 31 | "2) -r - Only the kernel version\n" 32 | "3) -i - All info of system and kernel\n"); 33 | } else { 34 | printf("%s. For more info about this tool, please do 'uname --help'\n", utsname.sysname); 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /programs/uptime.c: -------------------------------------------------------------------------------- 1 | /// @file uptime.c 2 | /// @brief 3 | /// @copyright (c) 2014-2024 This file is distributed under the MIT License. 4 | /// See LICENSE.md for details. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | int uptime_fd = open("/proc/uptime", O_RDONLY, 0600); 15 | if (uptime_fd == -1) { 16 | printf("Impossible to retrieve /proc/uptime file"); 17 | return -1; 18 | } 19 | 20 | // Read the content of /proc/uptime 21 | 22 | char buffer[64]; 23 | if (read(uptime_fd, buffer, sizeof(char) * 64) == -1) { 24 | printf("Impossible to read /proc/uptime content"); 25 | return -1; 26 | } 27 | 28 | char *endptr; 29 | long uptime = strtol(buffer, &endptr, 10); 30 | if (*endptr != '\0' && *endptr != ' ') { 31 | printf("Conversion error occurred\n"); 32 | return -1; 33 | } 34 | 35 | // Transform uptime into hours, days, mins, and seconds 36 | 37 | int updays = uptime / 86400; 38 | int uphours = (uptime - (updays * 86400)) / 3600; 39 | int upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60; 40 | int upseconds = (uptime - (updays * 86400) - (uphours * 3600) - (upmins * 60)); 41 | 42 | printf("Days: %d Hours: %d Minutes: %d Seconds: %d \n", updays, uphours, upmins, upseconds); 43 | close(uptime_fd); 44 | return 0; 45 | } 46 | --------------------------------------------------------------------------------