Compare commits

...

51 Commits

Author SHA1 Message Date
2d0245f2ac
feat(kernel): move kernel note to a separate file
Some checks failed
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Deploy Website / Deploy Website to GitHub Pages (push) Has been cancelled
Build OS / Analyze (c-cpp) (push) Has been cancelled
Build OS / Build OS (push) Has been cancelled
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 03:29:40 +00:00
79e55140e3
feat(kernel/driver): implement driver sha512 verification
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 03:23:25 +00:00
ae7f39d0de
feat(kernel/drivers): add trusted drivers list
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 03:22:40 +00:00
be72d2dc06
fix(kernel/driver): filter out non-.drv files in driver loading
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 03:21:32 +00:00
a8e4dd08bb
feat(kernel): add SHA-512 implementation
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 03:15:57 +00:00
c2e31827d8
refactor(kernel): remove unused TaskingPanic() function
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 02:19:01 +00:00
7087ce7ec5
feat(userspace/libc): implement brk(), chdir() and getcwd()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 02:01:57 +00:00
36bb7b7a88
refactor: sync headers
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 02:00:10 +00:00
2080d1f2b7
feat(kernel/syscalls): add fcntl() syscall
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:58:14 +00:00
b05a6a14e8
fix(kernel): compilation issues due to header changes
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:57:51 +00:00
c4225f7bdf
feat(userspace/coreutils): improve fennix shell implementation
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:27:09 +00:00
76b3d30db9
build(userspace/libc): correctly detect linux in cmake
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:17:44 +00:00
e89e984ccb
feat(userspace/libc): implement access()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:17:21 +00:00
dd1ffe0d17
fix(userspace/libc): add .gitkeep to arch directories
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:16:58 +00:00
3feb4e72aa
refactor(userspace/coreutils): change code style
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:16:21 +00:00
a43fac0c2d
feat(kernel/api): add fcntl.h
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-21 01:12:08 +00:00
67a3527e29
fix(userspace): change version of libc and coreutils
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-20 00:10:06 +00:00
f4a96e0b2e
docs: add note in echo.c PrintHelp()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-17 23:22:00 +00:00
7e69b8f82a
feat(userspace/libc): support for linux target
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-17 23:18:54 +00:00
8258d40115
feat(userspace/coreutils): add stub "sh" command
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-17 02:26:47 +00:00
568dffbca1
feat(userspace/libc): add <getopt.h> header
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 03:14:14 +00:00
9a82d812d6
feat(userspace/libc): add <regex.h> header
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 01:43:57 +00:00
49ee634822
feat(userspace/coreutils): add alias command
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 00:54:59 +00:00
babf792c30
feat(userspace/coreutils): add stub "admin" command
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/admin.html
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 00:47:56 +00:00
65f9a805e2
build(userspace/coreutils): generate symlink "[" on install
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 00:25:04 +00:00
6e077acc66
fix(userspace/coreutils): fix test command to correctly detect the bracket
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 00:15:51 +00:00
5af9c9b0a2
feat(userspace/coreutils): add test command
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-16 00:00:09 +00:00
201ace7eec
refactor(userspace): build using cmake
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-15 23:05:17 +00:00
40f46312f8
fix(userspace/apps/test): make gcc shut up about "infinite recursion detected"
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-13 23:25:52 +00:00
a53d41008c
fix(userspace/coreutils): handle combined uname options (-sv, -np, etc.)
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-11 15:38:07 +00:00
8a6910bf04
refactor(userspace/coreutils): improve uname command
The IEEE Std 1003.1-2024 specifies this for output:

    By default, the output shall be a single line of the following form:

    "%s\n", <sysname>

    If the -a option is specified, the output shall be a single line of the following form:

    "%s %s %s %s %s\n", <sysname>, <nodename>, <release>,
        <version>, <machine>

    Additional implementation-defined symbols may be written; all such symbols shall be written at the end of the line of output before the <newline>.

    If options are specified to select different combinations of the symbols, only those symbols shall be written, in the order shown above for the -a option. If a symbol is not selected for writing, its corresponding trailing <blank> characters also shall not be written.

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-11 15:33:08 +00:00
1d7a9edd46
feat(userspace/coreutils): implement arch command
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-11 15:29:17 +00:00
58477bae6a
refactor(userspace): move uname program to coreutils
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-11 00:53:36 +00:00
cbc6238d9d
fix(userspace/libc): implement uname()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 22:39:26 +00:00
9f393754f6
feat(kernel/syscalls): implement uname syscall
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 22:38:52 +00:00
fc43512c75
feat: add /etc/hostname file
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 22:05:54 +00:00
551853c5d6
fix(userspace/libc): implement gethostname()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 22:05:28 +00:00
6b4faf9f78
fix(userspace/libc): remove stub macros in termios.c
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 21:04:53 +00:00
4a6cf4f2e5
chore(userspace/coreutils): update .gitignore
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 19:34:35 +00:00
b008b8089c
fix(userspace/libc): missing include <sys/ioctl.h>
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 19:32:16 +00:00
2f33ea4dfd
build(devcontainer): install cmake too
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 13:48:23 +00:00
87540ab0b9
feat(coreutils): implement coreutils and compile it using cmake
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 02:29:14 +00:00
88a3b0912b
feat(userspace): add dummy libstdc++ library
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 02:20:32 +00:00
7ec85e67df
style(kernel): format document
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 01:14:47 +00:00
67692f2cef
feat(userspace/libc): define TIOC*WINSZ constants in <sys/ioctl.h>
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 01:14:18 +00:00
cc81facf50
feat(userspace/apps/usr): stub implementation for mdview
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 01:12:10 +00:00
95cc190b54
build(devcontainer): potential fix for "failed to initialize kvm: Permission denied"
qemu-system-x86_64: Could not access KVM kernel module: Permission denied
qemu-system-x86_64: failed to initialize kvm: Permission denied

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-10 01:07:56 +00:00
1c842ef3d1
docs: update build instructions
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-08 00:47:43 +00:00
27ad61fa17
chore(devcontainer): cleanup devcontainer.json file
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-07 22:58:04 +00:00
45d34c688f
fix(userspace/libc): fix puts() in interpreter
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-07 02:09:16 +00:00
1ff62e22bf
feat(kernel/syscalls): implement sys_fork()
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-07 01:31:50 +00:00
146 changed files with 8646 additions and 2850 deletions

View File

@ -94,7 +94,8 @@ RUN apt-get -y install --no-install-recommends \
grub-pc-bin \
grub-pc \
grub2-common \
pip
pip \
cmake
# Install git-cliff
RUN pip install git-cliff --break-system-packages

View File

@ -26,26 +26,24 @@
},
// From this line below are for qemu, so not that important.
"mounts": [
"source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached",
"source=${localEnv:XAUTHORITY},target=/home/vscode/.Xauthority,type=bind,consistency=cached",
"source=/dev/kvm,target=/dev/kvm,type=bind,consistency=cached",
"source=/run/user/1000/pulse/native,target=/run/user/1000/pulse/native,type=bind,consistency=cached"
{
"source": "/tmp/.X11-unix",
"target": "/tmp/.X11-unix",
"type": "bind"
},
{
"source": "${localEnv:XAUTHORITY}",
"target": "/home/vscode/.Xauthority",
"type": "bind"
},
{
"source": "/run/user/1000/pulse/native",
"target": "/run/user/1000/pulse/native",
"type": "bind"
}
],
"runArgs": [
"--privileged"
]
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "gcc -v",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
],
"postAttachCommand": "sudo chmod 666 /dev/kvm"
}

View File

@ -19,3 +19,8 @@ indent_size = 2
[{CMakeLists.txt,*.cmake}]
indent_size = 2
indent_style = space
[*.md]
indent_style = space
indent_size = 4
trim_trailing_whitespace = false

View File

@ -43,30 +43,37 @@ endif
export DRIVER_LDFLAGS
export DRIVER_CFLAGS
copy_driver_signatures:
@echo "const char *trusted_drivers[] = {" > $(OUTPUT_DIR)../../Kernel/drivers/trusted.c
@find $(OUTPUT_DIR) -name "*.drv" -exec sha512sum {} \; | awk '{gsub(/.*\//, "", $$2); gsub(/\./, "_", $$2); sub(/_drv$$/, "_drv", $$2); print "\"" $$1 "\"," }' >> $(OUTPUT_DIR)../../Kernel/drivers/trusted.c
@echo "};" >> $(OUTPUT_DIR)../../Kernel/drivers/trusted.c
@echo "const __SIZE_TYPE__ trusted_drivers_count = sizeof(trusted_drivers) / sizeof(trusted_drivers[0]);" >> $(OUTPUT_DIR)../../Kernel/drivers/trusted.c
build:
cp -rf ../Kernel/include/interface/* include/
mkdir -p out
make -C library build
$(MAKE) -C library build
ifneq ($(filter amd64 i386,$(OSARCH)),)
make -C audio build
make -C input build
make -C misc build
make -C network build
make -C storage build
make -C filesystem build
$(MAKE) -C audio build
$(MAKE) -C input build
$(MAKE) -C misc build
$(MAKE) -C network build
$(MAKE) -C storage build
$(MAKE) -C filesystem build
endif
$(MAKE) copy_driver_signatures
prepare:
$(info Nothing to prepare)
clean:
rm -rf out
make -C library clean
$(MAKE) -C library clean
ifneq ($(filter amd64 i386,$(OSARCH)),)
make -C audio clean
make -C input clean
make -C misc clean
make -C network clean
make -C storage clean
make -C filesystem clean
$(MAKE) -C audio clean
$(MAKE) -C input clean
$(MAKE) -C misc clean
$(MAKE) -C network clean
$(MAKE) -C storage clean
$(MAKE) -C filesystem clean
endif

File diff suppressed because it is too large Load Diff

109
Drivers/include/fcntl.h Normal file
View File

@ -0,0 +1,109 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_FCNTL_H__
#define __FENNIX_API_FCNTL_H__
#ifdef __kernel__
#include <types.h>
#endif
/* cmd */
#define F_DUPFD 0x1
#define F_DUPFD_CLOEXEC 0x101
#define F_DUPFD_CLOFORK 0x201
#define F_GETFD 0x2
#define F_SETFD 0x3
#define F_GETFL 0x4
#define F_SETFL 0x5
#define F_GETLK 0x6
#define F_SETLK 0x7
#define F_SETLKW 0x8
#define F_OFD_GETLK 0x9
#define F_OFD_SETLK 0xA
#define F_OFD_SETLKW 0xB
#define F_GETOWN 0xC
#define F_GETOWN_EX 0xD
#define F_SETOWN 0xE
#define F_SETOWN_EX 0xF
#define FD_CLOEXEC 0x1
#define FD_CLOFORK 0x2
/* l_type */
#define F_RDLCK 0x1
#define F_UNLCK 0x2
#define F_WRLCK 0x3
/* type */
#define F_OWNER_PID 0
#define F_OWNER_PGRP 1
/* oflag */
#define O_CLOEXEC 02000000
#define O_CLOFORK 04000000
#define O_CREAT 0x8
#define O_DIRECTORY 0200000
#define O_EXCL 0x20
#define O_NOCTTY 0x40
#define O_NOFOLLOW 0400000
#define O_TRUNC 0x400
#define O_TTY_INIT 0x800
#define O_APPEND 0x4
#define O_DSYNC 0x10
#define O_NONBLOCK 0x80
#define O_RSYNC 0x100
#define O_SYNC 0x200
#define O_ACCMODE 0x3
#define O_EXEC 0x4
#define O_RDONLY 0x1
#define O_RDWR 0x3
#define O_SEARCH 0x10
#define O_WRONLY 0x2
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#endif // !__FENNIX_API_FCNTL_H__

View File

@ -95,16 +95,6 @@
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)

View File

@ -15,8 +15,18 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#if __has_include(<interface/fcntl.h>)
#include <interface/fcntl.h>
#else
#include <fcntl.h>
#endif
#ifndef __fennix__
#error "__fennix__ not defined"
#endif
#pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum
{
__SYS_O_RDONLY = 0x1,
__SYS_O_WRONLY = 0x2,
__SYS_O_RDWR = 0x3,
__SYS_O_APPEND = 0x4,
__SYS_O_CREAT = 0x8,
__SYS_O_DSYNC = 0x10,
__SYS_O_EXCL = 0x20,
__SYS_O_NOCTTY = 0x40,
__SYS_O_NONBLOCK = 0x80,
__SYS_O_RSYNC = 0x100,
__SYS_O_SYNC = 0x200,
__SYS_O_TRUNC = 0x400
__SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t;
typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/
#define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/**
* @brief List of syscalls
*
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid
*/
SYS_IOCTL,
/**
* @brief Function control
*
* @code
* int fcntl(int fd, int cmd, void *arg);
* @endcode
*
* @details Manipulates the underlying parameters of a device.
*
* @param fd File descriptor referring to the device
* @param cmd Device-specific request code
* @param arg Argument for the request
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not valid
* - #EINVAL if the request is invalid
*/
SYS_FCNTL,
/* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied
*/
SYS_RENAME,
/**
* @brief Get unix name information
*
* @code
* int uname(struct kutsname *buf);
* @endcode
*
* @details Retrieves information about the operating system.
*
* @param buf Pointer to `kutsname` structure to store information
*
* @return
* - #EOK on success
* - #EFAULT if `buf` is outside accessible address space
*/
SYS_UNAME,
/**
* @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
/** @copydoc SYS_FCNTL */
#define call_fcntl(fd, cmd, arg) syscall3(SYS_FCNTL, (scarg)fd, (scarg)cmd, (scarg)arg)
/* File Status */
/** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

View File

@ -12,13 +12,16 @@
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"userspace",
"userspace/libc",
"vscode",
"userspace/apps/sys/init",
"userspace/libs/libm",
"devcontainer",
"userspace/coreutils",
"userspace/apps",
"userspace/libs",
"userspace/apps/test"
"userspace/apps/sys",
"userspace/apps/test",
"userspace/apps/usr",
"devcontainer",
"vscode"
]
}
}

72
INSTALL.md Normal file
View File

@ -0,0 +1,72 @@
# 🚀 Installation Guide
This guide will help you install Fennix on your system.
## 🛠️ Preparing the Environment
There are two ways to build the project:
1. **🐳 Use Dev Container (Recommended)**
* This is the easiest way to prepare the environment for building the project. But firstly, you need to install [Docker](https://docs.docker.com/get-docker/) and [Visual Studio Code](https://code.visualstudio.com/).
* After installing Docker and Visual Studio Code, you can open the project in Visual Studio Code and click on the "Reopen in Container" button.
* This will open the project in a Dev Container with all the required tools installed.
* If you encounter errors while the Dev Container is building, ensure the following are correctly configured:
* `/tmp/.X11-unix`
* Environment variable `XAUTHORITY`
* `/run/user/1000/pulse/native`
* **Note:** These configurations are only necessary if you plan to use QEMU inside the container.
2. **💻 Build the Project Locally**
* The instructions below will guide you through the process of building the project locally.
**NOTE:** You MUST have `autoconf 2.69` and `automake 1.15.1` versions installed on your system. A complete list of dependencies can be found in the [.devcontainer/Dockerfile](.devcontainer/Dockerfile) file.
Before building the project, you need to build the cross-compiler toolchain and QEMU.
You can do this by running the following command:
```sh
make setup
```
This will clone, patch, and build the required tools for you.
Alternatively, if you wish to skip building QEMU, you can run `make setup-no-qemu`.
However, in this case, you will need to manually specify the path to the QEMU binary in the `config.mk` file.
## 🏗️ Building the Project
To build the project, run:
```sh
make build
```
This will build the kernel, userspace, and drivers. The resulting ISO image will be `Fennix.iso`.
## 🚀 Running the OS
To run the OS, execute:
```sh
make run
```
The `run` target will automatically build the project if it hasn't been built yet.
## ⚙️ Additional Configuration
You can customize the project by editing the `config.mk` file.
## 🧪 Debugging
If you use Visual Studio Code, you can press `F5` to start debugging the OS.
The configuration is already set up for you.
Alternatively, you can run the following command to start debugging:
```sh
make debug
```
This will start QEMU in debug mode, allowing you to connect to it using GDB.
The GDB FIFO file is located at `/tmp/gdb-fennix`.

View File

@ -9,6 +9,6 @@
#define __kernel__ 1
#define KERNEL_NAME "Fennix"
#define KERNEL_ARCH "amd64"
#define KERNEL_VERSION "1.0"
#define KERNEL_VERSION "1.0.0"
#define GIT_COMMIT "0000000000000000000000000000000000000000"
#define GIT_COMMIT_SHORT "0000000"

View File

@ -26,14 +26,48 @@
#include <exec.hpp>
#include <rand.hpp>
#include <cwalk.h>
#include <sha512.h>
#include <md5.h>
#include "../../kernel.h"
using namespace vfs;
extern const char *trusted_drivers[];
extern const __SIZE_TYPE__ trusted_drivers_count;
namespace Driver
{
bool Manager::IsDriverTrusted(FileNode *File)
{
kstat st;
File->Stat(&st);
std::unique_ptr<uint8_t[]> ptr(new uint8_t[st.Size]);
File->Read(ptr.get(), st.Size, 0);
uint8_t *sha = sha512_sum(ptr.get(), st.Size);
char hash_str[129];
for (int j = 0; j < 64; j++)
sprintf(hash_str + j * 2, "%02x", sha[j]);
hash_str[128] = '\0';
for (__SIZE_TYPE__ i = 0; i < trusted_drivers_count; i++)
{
if (strcmp(hash_str, trusted_drivers[i]) == 0)
{
kfree(sha);
return true;
}
else
{
trace("Expected \"%s\" but got \"%s\" for driver %s",
trusted_drivers[i], hash_str, File->GetName().c_str());
}
}
kfree(sha);
return false;
}
void Manager::PreloadDrivers()
{
debug("Initializing driver manager");
@ -82,9 +116,19 @@ namespace Driver
if (!drvNode->IsRegularFile())
continue;
if (std::string(drvNode->Path).find(".drv") == std::string::npos)
continue;
if (Execute::GetBinaryType(drvNode->Path) != Execute::BinTypeELF)
{
error("Driver %s is not an ELF binary", drvNode->Path.c_str());
error("Driver %s is not an ELF binary", drvNode->GetPath().c_str());
continue;
}
if (!IsDriverTrusted(drvNode))
{
error("Driver %s is not trusted", drvNode->GetName().c_str());
KPrint("%s is not in the list of trusted drivers", drvNode->GetName().c_str());
continue;
}

4
Kernel/drivers/trusted.c Normal file
View File

@ -0,0 +1,4 @@
const char *trusted_drivers[] = {
"ae08d2e120c8370278ca9e17085a6b9e2f4a470ab6cec824c77ab1f8706c7144f5d4e1c9820914ed4fc7a4fd22de4b18bfed7c3b5d9c1e604e82280d7d45a5c7",
};
const __SIZE_TYPE__ trusted_drivers_count = sizeof(trusted_drivers) / sizeof(trusted_drivers[0]);

View File

@ -122,6 +122,7 @@ namespace Driver
FileNode *devNode = nullptr;
FileNode *devInputNode = nullptr;
bool IsDriverTrusted(FileNode *File);
int LoadDriverFile(DriverObject &Drv, FileNode *File);
void ReloadDriver(dev_t driverID);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_FCNTL_H__
#define __FENNIX_API_FCNTL_H__
#ifdef __kernel__
#include <types.h>
#endif
/* cmd */
#define F_DUPFD 0x1
#define F_DUPFD_CLOEXEC 0x101
#define F_DUPFD_CLOFORK 0x201
#define F_GETFD 0x2
#define F_SETFD 0x3
#define F_GETFL 0x4
#define F_SETFL 0x5
#define F_GETLK 0x6
#define F_SETLK 0x7
#define F_SETLKW 0x8
#define F_OFD_GETLK 0x9
#define F_OFD_SETLK 0xA
#define F_OFD_SETLKW 0xB
#define F_GETOWN 0xC
#define F_GETOWN_EX 0xD
#define F_SETOWN 0xE
#define F_SETOWN_EX 0xF
#define FD_CLOEXEC 0x1
#define FD_CLOFORK 0x2
/* l_type */
#define F_RDLCK 0x1
#define F_UNLCK 0x2
#define F_WRLCK 0x3
/* type */
#define F_OWNER_PID 0
#define F_OWNER_PGRP 1
/* oflag */
#define O_CLOEXEC 02000000
#define O_CLOFORK 04000000
#define O_CREAT 0x8
#define O_DIRECTORY 0200000
#define O_EXCL 0x20
#define O_NOCTTY 0x40
#define O_NOFOLLOW 0400000
#define O_TRUNC 0x400
#define O_TTY_INIT 0x800
#define O_APPEND 0x4
#define O_DSYNC 0x10
#define O_NONBLOCK 0x80
#define O_RSYNC 0x100
#define O_SYNC 0x200
#define O_ACCMODE 0x3
#define O_EXEC 0x4
#define O_RDONLY 0x1
#define O_RDWR 0x3
#define O_SEARCH 0x10
#define O_WRONLY 0x2
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#endif // !__FENNIX_API_FCNTL_H__

View File

@ -95,16 +95,6 @@
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)

View File

@ -15,8 +15,18 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#if __has_include(<interface/fcntl.h>)
#include <interface/fcntl.h>
#else
#include <fcntl.h>
#endif
#ifndef __fennix__
#error "__fennix__ not defined"
#endif
#pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum
{
__SYS_O_RDONLY = 0x1,
__SYS_O_WRONLY = 0x2,
__SYS_O_RDWR = 0x3,
__SYS_O_APPEND = 0x4,
__SYS_O_CREAT = 0x8,
__SYS_O_DSYNC = 0x10,
__SYS_O_EXCL = 0x20,
__SYS_O_NOCTTY = 0x40,
__SYS_O_NONBLOCK = 0x80,
__SYS_O_RSYNC = 0x100,
__SYS_O_SYNC = 0x200,
__SYS_O_TRUNC = 0x400
__SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t;
typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/
#define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/**
* @brief List of syscalls
*
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid
*/
SYS_IOCTL,
/**
* @brief Function control
*
* @code
* int fcntl(int fd, int cmd, void *arg);
* @endcode
*
* @details Manipulates the underlying parameters of a device.
*
* @param fd File descriptor referring to the device
* @param cmd Device-specific request code
* @param arg Argument for the request
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not valid
* - #EINVAL if the request is invalid
*/
SYS_FCNTL,
/* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied
*/
SYS_RENAME,
/**
* @brief Get unix name information
*
* @code
* int uname(struct kutsname *buf);
* @endcode
*
* @details Retrieves information about the operating system.
*
* @param buf Pointer to `kutsname` structure to store information
*
* @return
* - #EOK on success
* - #EFAULT if `buf` is outside accessible address space
*/
SYS_UNAME,
/**
* @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
/** @copydoc SYS_FCNTL */
#define call_fcntl(fd, cmd, arg) syscall3(SYS_FCNTL, (scarg)fd, (scarg)cmd, (scarg)arg)
/* File Status */
/** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

44
Kernel/include/sha512.h Normal file
View File

@ -0,0 +1,44 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_SHA512_H__
#define __FENNIX_KERNEL_SHA512_H__
#include <types.h>
#define SHA512_BLOCK_SIZE 128
#define SHA512_DIGEST_SIZE 64
typedef struct
{
uint64_t state[8];
uint64_t bitlen;
uint8_t data[SHA512_BLOCK_SIZE];
size_t datalen;
} SHA512_CTX;
START_EXTERNC
void sha512_transform(SHA512_CTX *ctx, const uint8_t *data);
void sha512_init(SHA512_CTX *ctx);
void sha512_update(SHA512_CTX *ctx, const uint8_t *data, size_t len);
void sha512_final(SHA512_CTX *ctx, uint8_t *hash);
uint8_t *sha512_sum(const uint8_t *input, size_t len);
END_EXTERNC
#endif // !__FENNIX_KERNEL_SHA512_H__

View File

@ -20,4 +20,18 @@
#include <interface/errno.h>
#ifdef __cplusplus
extern "C"
{
#endif
int *__errno_location(void) __attribute__((const));
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#define errno (*__errno_location())
#endif // !__FENNIX_KERNEL_STD_ERRNO_H__

View File

@ -50,30 +50,30 @@
#define I_GETCLTIME (__SID | 33)
#define I_CANPUT (__SID | 34)
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSID 0x5429
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSID 0x5429
#endif

View File

@ -412,79 +412,3 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
debug("Done.");
}
#pragma GCC diagnostic pop
EXTERNC void TaskingPanic()
{
if (TaskManager)
TaskManager->Panic();
}
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
} __attribute__((packed));
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(GIT_COMMIT),
};

View File

@ -62,7 +62,6 @@ EXTERNC void _KPrint(const char *Format, va_list Args);
EXTERNC void KPrint(const char *Format, ...);
EXTERNC void Entry(struct BootInfo *Info);
EXTERNC void BeforeShutdown(bool Reboot);
EXTERNC void TaskingPanic();
EXTERNC void KernelVFS();
EXTERNC void KernelMainThread();

86
Kernel/kernel_note.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
} __attribute__((packed));
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(GIT_COMMIT),
};

175
Kernel/library/sha512.c Normal file
View File

@ -0,0 +1,175 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sha512.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
static const uint64_t sha512_K[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
#define CH(x, y, z) ((x & y) ^ (~x & z))
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SIGMA0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
#define SIGMA1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (x >> 7))
#define sigma1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (x >> 6))
static const uint64_t sha512_H0[8] = {
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179};
void sha512_transform(SHA512_CTX *ctx, const uint8_t *data)
{
uint64_t m[80], a, b, c, d, e, f, g, h, t1, t2;
size_t i;
for (i = 0; i < 16; ++i)
{
m[i] = ((uint64_t)data[i * 8] << 56) | ((uint64_t)data[i * 8 + 1] << 48) |
((uint64_t)data[i * 8 + 2] << 40) | ((uint64_t)data[i * 8 + 3] << 32) |
((uint64_t)data[i * 8 + 4] << 24) | ((uint64_t)data[i * 8 + 5] << 16) |
((uint64_t)data[i * 8 + 6] << 8) | ((uint64_t)data[i * 8 + 7]);
}
for (; i < 80; ++i)
m[i] = sigma1(m[i - 2]) + m[i - 7] + sigma0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 80; ++i)
{
t1 = h + SIGMA1(e) + CH(e, f, g) + sha512_K[i] + m[i];
t2 = SIGMA0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void sha512_init(SHA512_CTX *ctx)
{
memcpy(ctx->state, sha512_H0, sizeof(sha512_H0));
ctx->bitlen = 0;
ctx->datalen = 0;
}
void sha512_update(SHA512_CTX *ctx, const uint8_t *data, size_t len)
{
for (size_t i = 0; i < len; ++i)
{
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen != SHA512_BLOCK_SIZE)
continue;
sha512_transform(ctx, ctx->data);
ctx->bitlen += ctx->datalen * 8;
ctx->datalen = 0;
}
}
void sha512_final(SHA512_CTX *ctx, uint8_t *hash)
{
ctx->bitlen += ctx->datalen * 8;
ctx->data[ctx->datalen++] = 0x80;
if (ctx->datalen > 112)
{
while (ctx->datalen < SHA512_BLOCK_SIZE)
ctx->data[ctx->datalen++] = 0x00;
sha512_transform(ctx, ctx->data);
ctx->datalen = 0;
}
while (ctx->datalen < 112)
ctx->data[ctx->datalen++] = 0x00;
for (size_t i = 0; i < 8; ++i)
ctx->data[127 - i] = ctx->bitlen >> (i * 8);
sha512_transform(ctx, ctx->data);
for (size_t i = 0; i < 8; ++i)
{
hash[i * 8] = (ctx->state[i] >> 56) & 0xff;
hash[i * 8 + 1] = (ctx->state[i] >> 48) & 0xff;
hash[i * 8 + 2] = (ctx->state[i] >> 40) & 0xff;
hash[i * 8 + 3] = (ctx->state[i] >> 32) & 0xff;
hash[i * 8 + 4] = (ctx->state[i] >> 24) & 0xff;
hash[i * 8 + 5] = (ctx->state[i] >> 16) & 0xff;
hash[i * 8 + 6] = (ctx->state[i] >> 8) & 0xff;
hash[i * 8 + 7] = ctx->state[i] & 0xff;
}
}
uint8_t *sha512_sum(const uint8_t *input, size_t len)
{
SHA512_CTX ctx;
uint8_t *hash = (uint8_t *)malloc(SHA512_DIGEST_SIZE);
if (!hash)
return NULL;
sha512_init(&ctx);
sha512_update(&ctx, input, len);
sha512_final(&ctx, hash);
return hash;
}

View File

@ -201,7 +201,7 @@ typedef unsigned long timeu64_t;
typedef int clockid_t;
typedef long time64_t;
struct f_owner_ex
struct linux_f_owner_ex
{
int type;
pid_t pid;

View File

@ -135,6 +135,7 @@ static int sys_close(SysFrm *Frame, int fd)
}
static int sys_ioctl(SysFrm *Frame, int fd, unsigned long request, void *argp) { return -ENOSYS; }
static int sys_fcntl(SysFrm *Frame, int fd, int cmd, void *arg) { return -ENOSYS; }
static int sys_stat(SysFrm *Frame, const char *pathname, struct stat *statbuf) { return -ENOSYS; }
static int sys_fstat(SysFrm *Frame, int fd, struct stat *statbuf) { return -ENOSYS; }
static int sys_lstat(SysFrm *Frame, const char *pathname, struct stat *statbuf) { return -ENOSYS; }
@ -175,120 +176,14 @@ static off_t sys_seek(SysFrm *Frame, int fd, off_t offset, int whence)
return fdt->usr_lseek(fd, offset, whence);
}
static __noreturn void sys_exit(SysFrm *Frame, int status)
{
TCB *t = thisThread;
{
CriticalSection cs;
trace("Userspace thread %s(%d) exited with code %d (%#x)",
t->Name,
t->ID, status,
status < 0 ? -status : status);
t->SetState(Tasking::Zombie);
t->SetExitCode(status);
}
while (true)
t->GetContext()->Yield();
__builtin_unreachable();
}
static pid_t sys_fork(SysFrm *Frame) { return -ENOSYS; }
static int sys_execve(SysFrm *Frame, const char *pathname, char *const argv[], char *const envp[]) { return -ENOSYS; }
static pid_t sys_getpid(SysFrm *Frame) { return -ENOSYS; }
static pid_t sys_getppid(SysFrm *Frame) { return -ENOSYS; }
static pid_t sys_waitpid(pid_t pid, int *wstatus, int options) { return -ENOSYS; }
static int sys_kill(SysFrm *Frame, pid_t pid, int sig)
{
PCB *pcb = thisProcess->GetContext()->GetProcessByID(pid);
if (!pcb)
return -ESRCH;
/* TODO: Check permissions */
if (sig == 0)
return 0;
if (pid == 0)
{
bool found = false;
foreach (auto proc in pcb->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID == thisProcess->Security.ProcessGroupID)
{
debug("Sending signal %d to %s(%d)", sig, proc->Name, proc->ID);
proc->SendSignal(sig);
found = true;
}
}
if (!found)
return -ESRCH;
return 0;
}
if (pid == -1)
{
fixme("Sending signal %d to all processes except init", sig);
return -ENOSYS;
}
if (pid < -1)
{
fixme("Sending signal %d to process group %d", sig, pid);
return -ENOSYS;
}
return pcb->SendSignal(sig);
}
static int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4)
{
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
switch (option)
{
case __SYS_GET_GS:
{
auto arg = vma->UserCheckAndGetAddress((void *)arg1);
if (arg == nullptr)
return -EFAULT;
#if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE);
#endif
return 0;
}
case __SYS_SET_GS:
{
#if defined(__amd64__) || defined(__i386__)
CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, arg1);
#endif
return 0;
}
case __SYS_GET_FS:
{
auto arg = vma->UserCheckAndGetAddress((void *)arg1);
if (arg == nullptr)
return -EFAULT;
#if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE);
#endif
return 0;
}
case __SYS_SET_FS:
{
#if defined(__amd64__) || defined(__i386__)
CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, arg1);
#endif
return 0;
}
default:
return -EINVAL;
}
}
__noreturn void sys_exit(SysFrm *Frame, int status);
pid_t sys_fork(SysFrm *Frame);
int sys_execve(SysFrm *Frame, const char *pathname, char *const argv[], char *const envp[]);
pid_t sys_getpid(SysFrm *Frame);
pid_t sys_getppid(SysFrm *Frame);
pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
int sys_kill(SysFrm *Frame, pid_t pid, int sig);
int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4);
int sys_brk(SysFrm *Frame, void *end_data);
void *sys_mmap(SysFrm *Frame, void *addr, size_t length, int prot, int flags, int fd, off_t offset);
@ -318,6 +213,54 @@ static int sys_rmdir(SysFrm *Frame, const char *path) { return -ENOSYS; }
static int sys_unlink(SysFrm *Frame, const char *pathname) { return -ENOSYS; }
static int sys_rename(SysFrm *Frame, const char *oldpath, const char *newpath) { return -ENOSYS; }
static int sys_uname(SysFrm *Frame, struct kutsname *buf)
{
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
struct kutsname *pBuf = vma->UserCheckAndGetAddress(buf, sizeof(struct kutsname));
if (pBuf == nullptr)
return -EFAULT;
strncpy(pBuf->sysname, KERNEL_NAME, sizeof(pBuf->sysname));
char release[sizeof(pBuf->release)];
sprintf(release, "%s", KERNEL_VERSION);
strncpy(pBuf->release, release, sizeof(pBuf->release));
char version[sizeof(pBuf->version)];
bool isDebug = false;
#ifdef DEBUG
isDebug = true;
#endif
sprintf(version, "FNX-v%s-%s %s %s %s %s",
KERNEL_VERSION, GIT_COMMIT_SHORT,
isDebug ? "DEBUG" : "RELEASE",
__DATE__, __TIME__, __VERSION__);
strncpy(pBuf->version, version, sizeof(pBuf->version));
#if defined(__amd64__)
const char *osarch = "x86_64";
#elif defined(__i386__)
const char *osarch = "i386";
#elif defined(__aarch64__)
const char *osarch = "aarch64";
#elif defined(__arm__)
const char *osarch = "arm";
#else
const char *osarch = "unknown";
#endif
strncpy(pBuf->machine, osarch, sizeof(pBuf->machine));
debug("%s %s %s %s", pBuf->sysname, pBuf->release,
pBuf->version, pBuf->machine);
return 0;
}
static SyscallData scTbl[SYS_MAX] = {};
__constructor void __init_native_syscalls(void)
{
@ -333,6 +276,7 @@ __constructor void __init_native_syscalls(void)
scTbl[SYS_OPEN] = {"SYS_OPEN", (void *)sys_open};
scTbl[SYS_CLOSE] = {"SYS_CLOSE", (void *)sys_close};
scTbl[SYS_IOCTL] = {"SYS_IOCTL", (void *)sys_ioctl};
scTbl[SYS_FCNTL] = {"SYS_FCNTL", (void *)sys_fcntl};
/* File Status */
scTbl[SYS_STAT] = {"SYS_STAT", (void *)sys_stat};
@ -387,6 +331,7 @@ __constructor void __init_native_syscalls(void)
scTbl[SYS_RMDIR] = {"SYS_RMDIR", (void *)sys_rmdir};
scTbl[SYS_UNLINK] = {"SYS_UNLINK", (void *)sys_unlink};
scTbl[SYS_RENAME] = {"SYS_RENAME", (void *)sys_rename};
scTbl[SYS_UNAME] = {"SYS_UNAME", (void *)sys_uname};
}
uintptr_t HandleNativeSyscalls(SysFrm *Frame)

256
Kernel/syscalls/process.cpp Normal file
View File

@ -0,0 +1,256 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <interface/syscalls.h>
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../kernel.h"
using Tasking::PCB;
using Tasking::TCB;
__no_stack_protector void __ForkReturn(void *tableAddr)
{
#if defined(__amd64__)
asmv("movq %0, %%cr3" ::"r"(tableAddr)); /* Load process page table */
asmv("movq $0, %rax\n"); /* Return 0 */
asmv("movq %r8, %rsp\n"); /* Restore stack pointer */
asmv("movq %r8, %rbp\n"); /* Restore base pointer */
asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
#elif defined(__i386__)
#warning "__ForkReturn not implemented for i386"
#endif
__builtin_unreachable();
}
__noreturn void sys_exit(SysFrm *Frame, int status)
{
TCB *t = thisThread;
{
CriticalSection cs;
trace("Userspace thread %s(%d) exited with code %d (%#x)",
t->Name,
t->ID, status,
status < 0 ? -status : status);
t->SetState(Tasking::Zombie);
t->SetExitCode(status);
}
while (true)
t->GetContext()->Yield();
__builtin_unreachable();
}
pid_t sys_fork(SysFrm *Frame)
{
TCB *Thread = thisThread;
PCB *Parent = Thread->Parent;
PCB *NewProcess =
TaskManager->CreateProcess(Parent, Parent->Name,
Parent->Security.ExecutionMode,
true);
if (unlikely(!NewProcess))
{
error("Failed to create process for fork");
return -EAGAIN;
}
NewProcess->Security.ProcessGroupID = Parent->Security.ProcessGroupID;
NewProcess->Security.SessionID = Parent->Security.SessionID;
NewProcess->PageTable = Parent->PageTable->Fork();
NewProcess->vma->Table = NewProcess->PageTable;
NewProcess->vma->Fork(Parent->vma);
NewProcess->ProgramBreak->SetTable(NewProcess->PageTable);
NewProcess->FileDescriptors->Fork(Parent->FileDescriptors);
NewProcess->Executable = Parent->Executable;
NewProcess->CWD = Parent->CWD;
NewProcess->FileCreationMask = Parent->FileCreationMask;
TCB *NewThread =
TaskManager->CreateThread(NewProcess,
0,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
Thread->Info.Architecture,
Thread->Info.Compatibility,
true);
if (!NewThread)
{
error("Failed to create thread for fork");
delete NewProcess;
return -EAGAIN;
}
NewThread->Rename(Thread->Name);
TaskManager->UpdateFrame();
#if defined(__amd64__) || defined(__i386__)
NewThread->FPU = Thread->FPU;
#endif
NewThread->Stack->Fork(Thread->Stack);
NewThread->Info.Architecture = Thread->Info.Architecture;
NewThread->Info.Compatibility = Thread->Info.Compatibility;
NewThread->Security.IsCritical = Thread->Security.IsCritical;
NewThread->Registers = Thread->Registers;
#if defined(__amd64__)
NewThread->Registers.rip = (uintptr_t)__ForkReturn;
/* For sysretq */
NewThread->Registers.rdi = (uintptr_t)NewProcess->PageTable;
NewThread->Registers.rcx = Frame->ReturnAddress;
NewThread->Registers.r8 = Frame->StackPointer;
#else
#warning "sys_fork not implemented for other platforms"
#endif
#if defined(__amd64__) || defined(__i386__)
NewThread->GSBase = NewThread->ShadowGSBase;
NewThread->ShadowGSBase = Thread->ShadowGSBase;
NewThread->FSBase = Thread->FSBase;
#endif
debug("ret addr: %#lx, stack: %#lx ip: %#lx", Frame->ReturnAddress,
Frame->StackPointer, (uintptr_t)__ForkReturn);
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)",
Thread->Name, Thread->ID,
NewThread->Name, NewThread->ID);
NewThread->SetState(Tasking::Ready);
// Parent->GetContext()->Yield();
return (int)NewProcess->ID;
}
int sys_execve(SysFrm *Frame, const char *pathname, char *const argv[], char *const envp[])
{
return -ENOSYS;
}
pid_t sys_getpid(SysFrm *Frame)
{
return -ENOSYS;
}
pid_t sys_getppid(SysFrm *Frame)
{
return -ENOSYS;
}
pid_t sys_waitpid(pid_t pid, int *wstatus, int options)
{
return -ENOSYS;
}
int sys_kill(SysFrm *Frame, pid_t pid, int sig)
{
PCB *pcb = thisProcess->GetContext()->GetProcessByID(pid);
if (!pcb)
return -ESRCH;
/* TODO: Check permissions */
if (sig == 0)
return 0;
if (pid == 0)
{
bool found = false;
foreach (auto proc in pcb->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID == thisProcess->Security.ProcessGroupID)
{
debug("Sending signal %d to %s(%d)", sig, proc->Name, proc->ID);
proc->SendSignal(sig);
found = true;
}
}
if (!found)
return -ESRCH;
return 0;
}
if (pid == -1)
{
fixme("Sending signal %d to all processes except init", sig);
return -ENOSYS;
}
if (pid < -1)
{
fixme("Sending signal %d to process group %d", sig, pid);
return -ENOSYS;
}
return pcb->SendSignal(sig);
}
int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4)
{
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
switch (option)
{
case __SYS_GET_GS:
{
auto arg = vma->UserCheckAndGetAddress((void *)arg1);
if (arg == nullptr)
return -EFAULT;
#if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE);
#endif
return 0;
}
case __SYS_SET_GS:
{
#if defined(__amd64__) || defined(__i386__)
CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, arg1);
#endif
return 0;
}
case __SYS_GET_FS:
{
auto arg = vma->UserCheckAndGetAddress((void *)arg1);
if (arg == nullptr)
return -EFAULT;
#if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE);
#endif
return 0;
}
case __SYS_SET_FS:
{
#if defined(__amd64__) || defined(__i386__)
CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, arg1);
#endif
return 0;
}
default:
return -EINVAL;
}
}

View File

@ -111,6 +111,9 @@ setup:
$(MAKE) prepare
$(MAKE) tools
setup-no-qemu:
$(MAKE) --quiet -C tools ci
build: build_kernel build_bootloader build_userspace build_drivers build_image
dump:
@ -313,6 +316,8 @@ endif
vscode_debug: build_kernel build_userspace build_drivers build_image vscode_debug_only
debug: vscode_debug
qemu: qemu_vdisk clean_logs
touch serial.log
# x-terminal-emulator -e tail -f serial.log &

View File

@ -5,9 +5,9 @@
<p align="center">
<p align="center">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/EnderIce2/Fennix">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/EnderIce2/Fennix">
<img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/EnderIce2/Fennix/makefile.yml">
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/EnderIce2/Fennix">
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/EnderIce2/Fennix">
<img alt="GitHub License" src="https://img.shields.io/github/license/EnderIce2/Fennix">
</p>
</p>
@ -24,15 +24,15 @@
## Features
- 🧩 Flexible and modular
- You can easily choose the components you want to include in the kernel
- You can easily choose the components you want to include in the kernel
- 🎛️ Compatible with multiple platforms
- Supports i386, AMD64 and AArch64 platforms
- Supports i386, AMD64 and AArch64 platforms
- 📦 Support for different operating system binaries
- You can run Linux and Windows binaries
- You can run Linux and Windows binaries
- 🖨️ Driver support
- Supports a variety of drivers for different hardware components
- Supports a variety of drivers for different hardware components
- 📖 Detailed documentation
- The project is well-documented using Doxygen
- The project is well-documented using Doxygen
> [!IMPORTANT]
> Some features are still in development and may not be fully functional.
@ -43,75 +43,14 @@
You can download the development ISO image from the [Actions](https://github.com/EnderIce2/Fennix/actions/workflows/makefile.yml) tab on the GitHub repository.
### 🛠️ Compile from Source
### 🛠️ Prerequisites
To build the project, you need to have the following tools installed:
- `make`
- `gcc`
- `ld`
- ... and other standard Unix tools
- These can be installed using `build-essential` on Ubuntu or `base-devel` on Arch Linux
- `doxygen` (optional)
- To generate the documentation
### 🚀 Installation
You can install the project by building it from source.
#### Cloning the Repository
First, clone the repository using Git:
```sh
git clone https://github.com/EnderIce2/fennix.git
cd fennix
```
#### Preparing the Environment
Before building the project, you need to build the cross-compiler toolchain and QEMU. You can do this by running the following command:
```sh
make setup
```
This will clone, patch, and build the required tools for you.
#### Building the Project
To build the project, run:
```sh
make build
```
This will build the kernel, userspace, and drivers. The iso image will be `Fennix.iso`.
#### Running the OS
You can run the OS using QEMU. First, build the project, then run:
```sh
make run
```
#### Additional Configuration
You can configure the project by editing the `config.mk` file.
## 🧪 Debugging
If you use Visual Studio Code, you can press `F5` to start debugging the OS.
The configuration is already set up for you.
> [!TIP]
> Make sure you built the project at least once before debugging.
Check out the [installation guide](INSTALL.md) to compile the project from source.
## 📚 Documentation
The project documentation is generated using Doxygen.
The current documentation is available [here](https://fennix.enderice2.com/docs/index.html).
To generate the documentation, run:
```sh
@ -122,13 +61,13 @@ The documentation will be available in the `doxygen-doc/docs` directory.
## 👨‍💻 Contributing
Contributions are welcome!
Contributions are welcome!
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute to this project.
### Contributors
<a href="https://github.com/EnderIce2/Fennix/graphs/contributors">
<img src="https://contrib.rocks/image?repo=EnderIce2/Fennix" />
<img src="https://contrib.rocks/image?repo=EnderIce2/Fennix" />
</a>
## 📃 License

View File

@ -11,3 +11,7 @@ indent_size = 4
[Makefile]
indent_style = tab
[{CMakeLists.txt,*.cmake}]
indent_size = 2
indent_style = space

View File

@ -160,5 +160,30 @@
"*/"
],
"description": "Create libc license."
},
"Core Utilities License": {
"isFileTemplate": true,
"prefix": [
"license_coreutils",
],
"body": [
"/*",
"\tThis file is part of Fennix Core Utilities.",
"",
"\tFennix Core Utilities is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix Core Utilities is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create coreutils license."
}
}

View File

@ -4,12 +4,17 @@
"name": "Fennix x64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**"
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
],
"defines": [
"__debug_vscode__",
"DEBUG=\"1\""
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
@ -45,12 +50,17 @@
"name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**"
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
],
"defines": [
"__debug_vscode__",
"DEBUG=\"1\""
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
@ -86,12 +96,17 @@
"name": "Fennix Arm (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**"
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
],
"defines": [
"__debug_vscode__",
"DEBUG=\"1\""
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
@ -107,12 +122,17 @@
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**"
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
],
"defines": [
"__debug_vscode__",
"DEBUG=\"1\""
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
@ -126,4 +146,4 @@
}
],
"version": 4
}
}

View File

@ -6,3 +6,4 @@
#undef __APPLE__
#undef __clang__
#define __vscode__ 1
#define FENNIX_DYNAMIC_LOADER 1

View File

@ -1,5 +1,6 @@
{
"git.openRepositoryInParentFolders": "always",
"git.alwaysSignOff": true,
"git.defaultBranchName": "master"
}
"git.defaultBranchName": "master",
"cmake.ignoreCMakeListsMissing": true
}

View File

@ -0,0 +1,18 @@
{
"folders": [
{
"path": "./libc"
}
],
"settings": {
"terminal.integrated.cwd": "../../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"userspace/libc"
]
}
}

View File

@ -0,0 +1,18 @@
{
"folders": [
{
"path": "./coreutils"
}
],
"settings": {
"terminal.integrated.cwd": "../../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"userspace/coreutils"
]
}
}

View File

@ -35,11 +35,44 @@ create_out:
mkdir -p out/usr/share/doc
mkdir -p out/usr/share/info
mkdir -p out/usr/include
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
build_coreutils:
mkdir -p cache/coreutils
cd cache/coreutils && \
cmake $(WORKSPACE_DIR)/coreutils \
-DCMAKE_INSTALL_PREFIX:PATH=$(WORKSPACE_DIR)/out \
-DCMAKE_SYSROOT=$(WORKSPACE_DIR)/out \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
&& \
make -j$(shell nproc) && \
make install
define copy_generic_header
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/$(1) $(WORKSPACE_DIR)/libc/abis/fennix/generic/bits/$(1)
endef
build_libc:
$(call copy_generic_header,errno.h)
$(call copy_generic_header,syscalls.h)
$(call copy_generic_header,fcntl.h)
mkdir -p cache/libc
cd cache/libc && \
cmake $(WORKSPACE_DIR)/libc \
-DCMAKE_INSTALL_PREFIX:PATH=$(WORKSPACE_DIR)/out \
-DCMAKE_SYSROOT=$(WORKSPACE_DIR)/out \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
-DTARGET_OS=fennix \
-DTARGET_ARCH=$(OSARCH) \
&& \
make -j$(shell nproc) && \
make install
build: create_out
make -C libc build
$(MAKE) build_libc
make -C libs build
$(MAKE) build_coreutils
make -C apps build
prepare:
@ -49,6 +82,6 @@ clean:
rm -rf out cache
mkdir -p cache
touch cache/.gitkeep
make -C libc clean
make -C libs clean
make -C apps clean
make -C docker clean

View File

@ -1,119 +0,0 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <sys/utsname.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
void print_usage()
{
printf("Usage: uname [OPTION]...\n");
printf("Display specific system information. With no OPTION, defaults to -s.\n\n");
printf(" -a, --all display all information, in the following order,\n");
printf(" except omit -p and -i if unknown:\n");
printf(" -s, --kernel-name display the kernel name\n");
printf(" -n, --nodename display the network node hostname\n");
printf(" -r, --kernel-release display the kernel release\n");
printf(" -v, --kernel-version display the kernel version\n");
printf(" -m, --machine display the machine hardware name\n");
printf(" -p, --processor display the processor type (non-portable)\n");
printf(" -i, --hardware-platform display the hardware platform (non-portable)\n");
printf(" -o, --operating-system display the operating system\n");
printf(" --help show this help message and exit\n");
}
int main(int argc, char *argv[])
{
struct utsname buffer;
if (uname(&buffer) != 0)
{
perror("uname");
exit(EXIT_FAILURE);
}
bool print_all = false;
bool print_kernel_name = false;
bool print_nodename = false;
bool print_kernel_release = false;
bool print_kernel_version = false;
bool print_machine = false;
bool print_processor = false;
bool print_hardware_platform = false;
bool print_operating_system = false;
if (argc == 1)
print_kernel_name = true;
else
{
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
{
print_all = true;
break;
}
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--kernel-name") == 0)
print_kernel_name = true;
else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--nodename") == 0)
print_nodename = true;
else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--kernel-release") == 0)
print_kernel_release = true;
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--kernel-version") == 0)
print_kernel_version = true;
else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--machine") == 0)
print_machine = true;
else if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--processor") == 0)
print_processor = true;
else if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--hardware-platform") == 0)
print_hardware_platform = true;
else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--operating-system") == 0)
print_operating_system = true;
else if (strcmp(argv[i], "--help") == 0)
{
print_usage();
exit(EXIT_SUCCESS);
}
else
{
fprintf(stderr, "uname: invalid option -- '%s'\n", argv[i]);
print_usage();
exit(EXIT_FAILURE);
}
}
}
if (print_all || print_kernel_name)
printf("%s ", buffer.sysname);
if (print_all || print_nodename)
printf("%s ", buffer.nodename);
if (print_all || print_kernel_release)
printf("%s ", buffer.release);
if (print_all || print_kernel_version)
printf("%s ", buffer.version);
if (print_all || print_machine)
printf("%s ", buffer.machine);
if (print_all || print_processor)
printf("%s ", buffer.machine); /* FIXME */
if (print_all || print_hardware_platform)
printf("%s ", buffer.machine); /* FIXME */
if (print_all || print_operating_system)
printf("%s ", buffer.sysname); /* FIXME */
printf("\n");
return 0;
}

View File

@ -883,9 +883,12 @@ void fork_bomb_syscall()
#endif
}
volatile int __dummy = 0;
int fill_stack(void *p)
{
__attribute__((used)) char buf[512];
if (__dummy == 1)
return (int)(__UINTPTR_TYPE__)p;
char buf[512];
return fill_stack(buf);
}

View File

@ -0,0 +1,9 @@
MAKE_TARGETS := build clean
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
$(MAKE_TARGETS): $(DIRECTORIES)
$(DIRECTORIES):
$(MAKE) -C $@ $(MAKECMDGOALS)

View File

@ -11,7 +11,7 @@ FILENAME = $(notdir $(shell pwd))
WARNCFLAG = -Wall -Wextra
build: $(FILENAME).elf
cp $(FILENAME).elf $(WORKSPACE_DIR)/out/bin/$(FILENAME)
cp $(FILENAME).elf $(WORKSPACE_DIR)/out/usr/bin/$(FILENAME)
$(FILENAME).elf: $(OBJ)
$(info Linking $@)

View File

@ -0,0 +1,419 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_WHITE "\x1b[37m"
#define ANSI_COLOR_BLACK "\x1b[30m"
#define ANSI_COLOR_RESET "\x1b[0m"
#define ANSI_BG_BLACK "\x1b[40m"
#define ANSI_BG_RED "\x1b[41m"
#define ANSI_BG_GREEN "\x1b[42m"
#define ANSI_BG_YELLOW "\x1b[43m"
#define ANSI_BG_BLUE "\x1b[44m"
#define ANSI_BG_MAGENTA "\x1b[45m"
#define ANSI_BG_CYAN "\x1b[46m"
#define ANSI_BG_GRAY "\x1b[47m"
#define ANSI_BG_DARK_GRAY "\x1b[100m"
#define ANSI_BOLD "\x1b[1m"
#define ANSI_UNDERLINE "\x1b[4m"
#define ANSI_STRIKETHROUGH "\x1b[9m"
#define ANSI_HIGHLIGHT "\x1b[43m"
void print_horizontal_rule()
{
int width;
struct winsize ws;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
width = ws.ws_col;
for (int i = 0; i < width - 2; i++)
printf("-");
}
void print_admonition(const char *type, const char *title, const char *content)
{
if (strcmp(type, "warning") == 0)
{
printf(ANSI_BG_YELLOW);
printf(ANSI_COLOR_BLACK);
printf("! Warning: %s %s\n", title, content);
}
else if (strcmp(type, "note") == 0)
{
printf(ANSI_BG_BLUE);
printf(ANSI_COLOR_WHITE);
printf("i Note: %s %s\n", title, content);
}
else if (strcmp(type, "tip") == 0)
{
printf(ANSI_BG_GREEN);
printf(ANSI_COLOR_WHITE);
printf("? Tip: %s %s\n", title, content);
}
else if (strcmp(type, "important") == 0)
{
printf(ANSI_BG_RED);
printf(ANSI_COLOR_BLACK);
printf("! Important: %s %s\n", title, content);
}
else if (strcmp(type, "caution") == 0)
{
printf(ANSI_BG_MAGENTA);
printf(ANSI_COLOR_WHITE);
printf("! Caution: %s %s\n", title, content);
}
else if (strcmp(type, "danger") == 0)
{
printf(ANSI_BG_RED);
printf(ANSI_COLOR_BLACK);
printf("! Danger: %s %s\n", title, content);
}
printf(ANSI_COLOR_RESET);
}
void print_formatted_text(const char *text)
{
bool bold = false;
bool underline = false;
bool inline_code = false;
bool strikethrough = false;
bool highlight = false;
for (int i = 0; text[i] != '\0'; ++i)
{
if (strncmp(&text[i], "!!!", 3) == 0)
{
char admonition_type[20] = "";
char admonition_title[256] = "";
int type_start = i + 4;
int type_end = -1;
int title_start = -1;
int title_end = -1;
int content_start = -1;
for (int j = type_start; text[j] != '\0' && text[j] != ' ' && text[j] != '"'; ++j)
{
type_end = j;
}
if (type_end != -1)
{
strncpy(admonition_type, &text[type_start], type_end - type_start + 1);
admonition_type[type_end - type_start + 1] = '\0';
i = type_end + 1;
}
if (text[i] == ' ' && text[i + 1] == '"')
{
title_start = i + 2;
for (int j = title_start; text[j] != '\0' && text[j] != '"'; ++j)
{
title_end = j;
}
if (title_end != -1)
{
strncpy(admonition_title, &text[title_start], title_end - title_start + 1);
admonition_title[title_end - title_start + 1] = '\0';
i = title_end + 1;
}
}
content_start = i + 1;
print_admonition(admonition_type, admonition_title, text + content_start);
return;
}
if (text[i] == '`')
{
if (!inline_code)
{
printf(ANSI_BG_MAGENTA);
printf(ANSI_UNDERLINE);
printf(ANSI_BOLD);
inline_code = true;
}
else
{
printf(ANSI_COLOR_RESET);
inline_code = false;
}
}
else if (text[i] == '*' && text[i + 1] == '*')
{
if (!bold)
{
printf(ANSI_BOLD);
bold = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
bold = false;
i++;
}
}
else if (text[i] == '_' && text[i + 1] == '_')
{
if (!underline)
{
printf(ANSI_UNDERLINE);
underline = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
underline = false;
i++;
}
}
else if (text[i] == '~' && text[i + 1] == '~')
{
if (!strikethrough)
{
printf(ANSI_STRIKETHROUGH);
strikethrough = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
strikethrough = false;
i++;
}
}
else if (text[i] == '=' && text[i + 1] == '=')
{
if (!highlight)
{
printf(ANSI_HIGHLIGHT);
highlight = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
highlight = false;
i++;
}
}
else if (text[i] == '[')
{
int start_link_text = i + 1;
int end_link_text = -1;
int start_link_url = -1;
int end_link_url = -1;
for (int j = start_link_text; text[j] != '\0'; ++j)
{
if (text[j] == ']')
{
end_link_text = j;
if (text[j + 1] == '(')
{
start_link_url = j + 2;
for (int k = start_link_url; text[k] != '\0'; ++k)
{
if (text[k] == ')')
{
end_link_url = k;
break;
}
}
}
break;
}
}
if (end_link_text != -1 && start_link_url != -1 && end_link_url != -1)
{
char link_text[256];
strncpy(link_text, &text[start_link_text], end_link_text - start_link_text);
link_text[end_link_text - start_link_text] = '\0';
char link_url[256];
strncpy(link_url, &text[start_link_url], end_link_url - start_link_url);
link_url[end_link_url - start_link_url] = '\0';
printf(ANSI_UNDERLINE);
printf(link_text);
printf(ANSI_COLOR_RESET);
printf("(%s)", link_url);
i = end_link_url;
continue;
}
}
else if (text[i] == '<')
{
while (text[i] != '\0' && text[i] != '>')
{
i++;
}
if (text[i] == '>')
{
continue;
}
}
else if (strncmp(&text[i], "---\n", 4) == 0 || strncmp(&text[i], "***\n", 4) == 0 || strncmp(&text[i], "_________________\n", 18) == 0)
{
print_horizontal_rule();
i += 2;
continue;
}
else if (strncmp(&text[i], "- [x] ", 6) == 0)
{
printf("[X] ");
i += 5;
continue;
}
else if (strncmp(&text[i], "- [ ] ", 6) == 0)
{
printf("[ ] ");
i += 5;
continue;
}
else
{
printf("%c", text[i]);
}
}
printf(ANSI_COLOR_RESET);
}
void process_markdown_file(const char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL)
{
perror("fopen");
return;
}
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1)
{
if (strncmp(line, "# ", 2) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_UNDERLINE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "## ", 3) == 0)
{
printf(ANSI_BOLD);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "### ", 4) == 0)
{
printf(ANSI_UNDERLINE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "#### ", 5) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_UNDERLINE);
printf(ANSI_COLOR_RED);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "##### ", 6) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_COLOR_MAGENTA);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "###### ", 7) == 0)
{
printf(ANSI_UNDERLINE);
printf(ANSI_COLOR_BLUE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "```", 3) == 0)
{
printf(ANSI_BG_DARK_GRAY);
printf(ANSI_COLOR_WHITE);
printf("%s", line);
while ((read = getline(&line, &len, file)) != -1 && strncmp(line, "```", 3) != 0)
{
printf("%s", line);
}
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "> ", 2) == 0 && strncmp(line, ">> ", 3) != 0)
{
printf(ANSI_COLOR_WHITE);
printf(ANSI_BG_GRAY " " ANSI_BG_DARK_GRAY "%s", line + (strncmp(line, ">>", 2) == 0 ? 2 : 1));
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, ">\n", 2) == 0)
{
printf(ANSI_COLOR_WHITE);
printf(ANSI_BG_GRAY " \n");
printf(ANSI_COLOR_RESET);
}
else
{
print_formatted_text(line);
}
}
fclose(file);
if (line)
free(line);
}
void print_usage()
{
printf("Usage: mdview <markdown_file>\n");
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "mdview: invalid arguments\n");
print_usage();
exit(EXIT_FAILURE);
}
process_markdown_file(argv[1]);
return 0;
}

View File

@ -0,0 +1,436 @@
## Admonitions
> :warning: **Warning:** This is a warning.
> :memo: **Note:** This is a note.
> :bulb: **Tip:** This is a tip.
## GitHub Admonitions
> [!NOTE]
> This is a note.
> [!TIP]
> This is a tip.
> [!IMPORTANT]
> This is important.
> [!WARNING]
> This is a warning.
> [!CAUTION]
> This is a caution.
## python-markdown Admonitions
!!! note "This is a note."
Hello World!
!!! danger "This is a danger."
Hello World!
!!! important "This is important."
Hello World!
!!! warning "This is a warning."
Hello World!
!!! caution "This is a caution."
Hello World!
[The section below is an excerpt of the original.](https://www.markdownguide.org/cheat-sheet/)
The original content is licensed under a CC BY-SA 4.0 license. The original content can be found at the link above.
## Headings
# Heading level 1
## Heading level 2
### Heading level 3
#### Heading level 4
##### Heading level 5
###### Heading level 6
## Alternate Syntax
Heading level 1
===============
Heading level 2
---------------
---
## Paragraphs
I really like using Markdown.
I think I'll use it to format all of my documents from now on.
---
## Line Breaks
This is the first line.
And this is the second line.
---
## Emphasis
I just love **bold text**.
I just love __bold text__.
Love**is**bold
Italicized text is the *cat's meow*.
Italicized text is the _cat's meow_.
A*cat*meow
This text is ***really important***.
This text is ___really important___.
This text is __*really important*__.
This text is **_really important_**.
This is really***very***important text.
---
## Blockquotes
> Dorothy followed her through many of the beautiful rooms in her castle.
> Dorothy followed her through many of the beautiful rooms in her castle.
>
> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
> Dorothy followed her through many of the beautiful rooms in her castle.
>
>> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
> #### The quarterly results look great!
>
> - Revenue was off the chart.
> - Profits were higher than ever.
>
> *Everything* is going according to **plan**.
---
## Lists
List 1
1. First item
2. Second item
3. Third item
4. Fourth item
List 2
1. First item
1. Second item
1. Third item
1. Fourth item
List 3
1. First item
8. Second item
3. Third item
5. Fourth item
List 4
1. First item
2. Second item
3. Third item
1. Indented item
2. Indented item
4. Fourth item
List 5
- First item
- Second item
- Third item
- Fourth item
List 6
* First item
* Second item
* Third item
* Fourth item
List 7
+ First item
+ Second item
+ Third item
+ Fourth item
List 8
- First item
- Second item
- Third item
- Indented item
- Indented item
- Fourth item
List 9
- 1968\. A great year!
- I think 1969 was second best.
---
## Paragraphs
* This is the first list item.
* Here's the second list item.
I need to add another paragraph below the second list item.
* And here's the third list item.
* This is the first list item.
* Here's the second list item.
> A blockquote would look great below the second list item.
* And here's the third list item.
---
## Code Blocks
1. Open the file.
2. Find the following code block on line 21:
<html>
<head>
<title>Test</title>
</head>
3. Update the title to match the name of your website.
---
## Images
1. Open the file containing the Linux mascot.
2. Marvel at its beauty.
![Tux, the Linux mascot](https://mdg.imgix.net/assets/images/tux.png)
3. Close the file.
---
## Code
At the command prompt, type `nano`.
``Use `code` in your Markdown file.``
<html>
<head>
</head>
</html>
---
## Horizontal Rules
***
---
_________________
---
## Links
My favorite search engine is [Duck Duck Go](https://duckduckgo.com).
My favorite search engine is [Duck Duck Go](https://duckduckgo.com "The best search engine for privacy").
<https://www.markdownguide.org>
<fake@example.com>
I love supporting the **[EFF](https://eff.org)**.
This is the *[Markdown Guide](https://www.markdownguide.org)*.
See the section on [`code`](#code).
In a hole in the ground there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends
of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to
eat: it was a [hobbit-hole][1], and that means comfort.
[1]: <https://en.wikipedia.org/wiki/Hobbit#Lifestyle> "Hobbit lifestyles"
---
## Escaping Characters
\* Without the backslash, this would be a bullet in an unordered list.
\\ test
\` test
\* test
\_ test
\{ test
\} test
\[ test
\] test
\< test
\> test
\( test
\) test
\# test
\+ test
\- test
\. test
\! test
\| test
---
## HTML
This **word** is bold. This <em>word</em> is italic.
## Tables
| Syntax | Description |
| ----------- | ----------- |
| Header | Title |
| Paragraph | Text |
| Syntax | Description |
| --- | ----------- |
| Header | Title |
| Paragraph | Text |
| Syntax | Description | Test Text |
| :--- | :----: | ---: |
| Header | Title | Here's this |
| Paragraph | Text | And more |
---
## Fenced Code Blocks
```
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
```json
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
---
## Footnotes
Here's a simple footnote,[^1] and here's a longer one.[^bignote]
[^1]: This is the first footnote.
[^bignote]: Here's one with multiple paragraphs and code.
Indent paragraphs to include them in the footnote.
`{ my code }`
Add as many paragraphs as you like.
---
## Heading IDs
# Heading level 1 {#custom-id}
## Heading level 2 {#custom-id}
### Heading level 3 {#custom-id}
#### Heading level 4 {#custom-id}
##### Heading level 5 {#custom-id}
###### Heading level 6 {#custom-id}
---
## Strikethrough
~~The world is flat.~~ We now know that the world is round.
---
## Task Lists
- [x] Write the press release
- [ ] Update the website
- [ ] Contact the media
---
## Emoji
Gone camping! :tent: Be back soon.
That is so funny! :joy:
---
## Highlight
I need to highlight these ==very important words==.
---
## Subscript and Superscript
H~2~O
X^2^
---
## Disabling Automatic URL Linking
`http://www.example.com`

1
Userspace/coreutils/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.10)
project(FennixCoreUtilities VERSION 0.0.1)
if(NOT DEFINED ENV{WORKSPACE_DIR})
set(STANDALONE_BUILD ON)
message(STATUS "Compiling standalone")
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
endif()
set(CMAKE_C_COMPILER "$ENV{CC}")
set(CMAKE_CXX_COMPILER "$ENV{CXX}")
set(CMAKE_ASM_COMPILER "$ENV{AS}")
set(CMAKE_AR "$ENV{AR}")
set(CMAKE_LINKER "$ENV{LD}")
if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
else()
set(CMAKE_C_FLAGS "-O2")
endif()
include_directories(${CMAKE_SOURCE_DIR}/include)
file(GLOB SINGLE_SOURCE "src/*.c")
foreach(file ${SINGLE_SOURCE})
get_filename_component(name ${file} NAME_WE)
add_executable(${name} ${file})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()
file(GLOB_RECURSE GROUP_SOURCES "src/*/*.c")
foreach(file ${GROUP_SOURCES})
get_filename_component(name ${file} DIRECTORY)
get_filename_component(name ${name} NAME)
list(APPEND GROUP_MAP_${name} ${file})
endforeach()
foreach(name IN LISTS GROUP_MAP_)
add_executable(${name} ${GROUP_MAP_${name}})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()
if(UNIX AND TARGET test)
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
test
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/[\"
)")
endif()
if(UNIX AND TARGET sh)
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
sh
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/fsh\"
)")
endif()

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COREUTILS_H
#define _COREUTILS_H
#ifndef PROGRAM_NAME
#define PROGRAM_NAME "<unknown>"
#endif
#ifndef PROGRAM_VERSION
#define PROGRAM_VERSION "<unknown>"
#endif
#define BUILD_YEAR (__DATE__ + 7)
#define PRINTF_VERSION \
printf("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); \
printf("Fennix Core Utilities Copyright (C) %s EnderIce2\n", BUILD_YEAR); \
printf("This program comes with ABSOLUTELY NO WARRANTY\n"); \
printf("This is free software, and you are welcome to redistribute it\n"); \
printf("under certain conditions\n")
#endif // _COREUTILS_H

View File

@ -0,0 +1,25 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
fprintf(stderr, "stub\n");
return EXIT_FAILURE;
}

View File

@ -0,0 +1,225 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
typedef struct AliasData
{
char *name;
char *value;
struct AliasData *next;
} AliasData;
AliasData *Aliases = NULL;
void FreeAliases()
{
AliasData *current = Aliases;
while (current != NULL)
{
AliasData *next = current->next;
free(current->name);
free(current->value);
free(current);
current = next;
}
Aliases = NULL;
}
AliasData *FindAlias(const char *name)
{
AliasData *current = Aliases;
while (current != NULL)
{
if (strcmp(current->name, name) == 0)
return current;
current = current->next;
}
return NULL;
}
void AddAlias(const char *name, const char *value)
{
AliasData *existing = FindAlias(name);
if (existing)
{
free(existing->value);
existing->value = strdup(value);
return;
}
AliasData *new_alias = malloc(sizeof(AliasData));
new_alias->name = strdup(name);
new_alias->value = strdup(value);
new_alias->next = Aliases;
Aliases = new_alias;
}
int ReadAliases(const char *filename)
{
FILE *file = fopen(filename, "r");
if (!file)
return -1;
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1)
{
if (line[read - 1] == '\n')
line[read - 1] = '\0';
char *eq = strchr(line, '=');
if (!eq)
continue;
*eq = '\0';
AddAlias(line, eq + 1);
}
free(line);
fclose(file);
return 0;
}
int WriteAliases(const char *filename)
{
FILE *file = fopen(filename, "w");
if (!file)
{
perror("Error writing aliases");
return -1;
}
AliasData *current = Aliases;
while (current)
{
fprintf(file, "%s=%s\n", current->name, current->value);
current = current->next;
}
fclose(file);
return 0;
}
char *QuoteValue(const char *value)
{
size_t quotes = 0;
for (const char *p = value; *p; p++)
{
if (*p == '\'')
quotes++;
}
char *quoted = malloc(strlen(value) + quotes * 4 + 3);
if (!quoted)
return NULL;
char *dest = quoted;
*dest++ = '\'';
for (const char *p = value; *p; p++)
{
if (*p == '\'')
{
strcpy(dest, "'\\''");
dest += 4;
}
else
*dest++ = *p;
}
*dest++ = '\'';
*dest = '\0';
return quoted;
}
int main(int argc, char *argv[])
{
const char *home = getenv("HOME");
if (!home)
{
fprintf(stderr, "alias: HOME not set\n");
return 2;
}
char path[1024];
snprintf(path, sizeof(path), "%s/.aliases", home);
if (ReadAliases(path) == -1 && errno != ENOENT)
{
perror("Error reading aliases");
return 2;
}
int status = 0;
if (argc == 1)
{
AliasData *current = Aliases;
while (current)
{
char *q = QuoteValue(current->value);
printf("alias %s=%s\n", current->name, q);
free(q);
current = current->next;
}
}
else
{
for (int i = 1; i < argc; i++)
{
char *arg = argv[i];
char *eq = strchr(arg, '=');
if (eq)
{
*eq = '\0';
char *name = arg;
char *value = eq + 1;
AddAlias(name, value);
char *q = QuoteValue(value);
printf("alias %s=%s\n", name, q);
free(q);
}
else
{
AliasData *a = FindAlias(arg);
if (a)
{
char *q = QuoteValue(a->value);
printf("alias %s=%s\n", a->name, q);
free(q);
}
else
{
fprintf(stderr, "alias: %s: not found\n", arg);
status = 1;
}
}
}
}
if (WriteAliases(path) == -1)
status = 1;
FreeAliases();
return status;
}

View File

@ -0,0 +1,68 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <coreutils.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/utsname.h>
void PrintUsage()
{
printf("Usage: arch [OPTION]...\n");
printf("Display the machine hardware architecture name.\n\n");
printf(" --help show this help message and exit\n");
printf(" --version output version information and exit\n");
}
int main(int argc, char *argv[])
{
struct utsname buffer;
if (uname(&buffer) != 0)
{
perror("uname");
exit(EXIT_FAILURE);
}
if (argc == 1)
{
printf("%s\n", buffer.machine);
return 0;
}
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "--help") == 0)
{
PrintUsage();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[1], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
else
{
fprintf(stderr, "uname: invalid option -- '%s'\n", argv[i]);
exit(EXIT_FAILURE);
}
}
return 0;
}

View File

@ -0,0 +1,187 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <coreutils.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
void PrintHelp()
{
/**
* POSIX specification for echo specifies that
* "Implementations shall not support any options."
* but i will do this anyway.
*
* https://pubs.opengroup.org/onlinepubs/9799919799/utilities/echo.html
*/
printf("Usage: echo [OPTION]... [STRING]...\n");
printf("Echo the STRING(s) to standard output.\n\n");
printf(" -n do not output the trailing newline\n");
printf(" -e enable interpretation of backslash escapes\n");
printf(" -E disable interpretation of backslash escapes (default)\n");
printf(" --help display this help and exit\n");
printf(" --version output version information and exit\n\n");
printf("If -e is specified, the following sequences are recognized:\n");
printf(" \\\\ backslash\n");
printf(" \\a alert (BEL)\n");
printf(" \\b backspace\n");
printf(" \\c produce no further output\n");
printf(" \\e escape\n");
printf(" \\f form feed\n");
printf(" \\n new line\n");
printf(" \\r carriage return\n");
printf(" \\t horizontal tab\n");
printf(" \\v vertical tab\n");
}
void PrintEscaped(const char *str)
{
while (*str)
{
if (*str == '\\')
{
str++;
switch (*str)
{
case 'n':
putchar('\n');
break;
case 't':
putchar('\t');
break;
case '\\':
putchar('\\');
break;
case 'a':
putchar('\a');
break;
case 'b':
putchar('\b');
break;
case 'r':
putchar('\r');
break;
case 'v':
putchar('\v');
break;
case 'f':
putchar('\f');
break;
case '0' ... '7':
{
int octal = 0;
for (int i = 0; i < 3 && *str >= '0' && *str <= '7'; i++, str++)
octal = octal * 8 + (*str - '0');
putchar(octal);
str--;
break;
}
case 'x':
{
int hex = 0;
str++;
for (int i = 0; i < 2 && ((*str >= '0' && *str <= '9') ||
(*str >= 'a' && *str <= 'f') ||
(*str >= 'A' && *str <= 'F'));
i++, str++)
{
if (*str >= '0' && *str <= '9')
hex = hex * 16 + (*str - '0');
else if (*str >= 'a' && *str <= 'f')
hex = hex * 16 + (*str - 'a' + 10);
else if (*str >= 'A' && *str <= 'F')
hex = hex * 16 + (*str - 'A' + 10);
}
putchar(hex);
str--;
break;
}
default:
putchar(*str);
break;
}
}
else
putchar(*str);
str++;
}
}
int main(int argc, char *argv[])
{
bool newline = true;
bool interpretEscapes = false;
int argStart = 1;
if (argc == 2)
{
if (strcmp(argv[1], "--help") == 0)
{
PrintHelp();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[1], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
}
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-' && argv[i][1] != '\0')
{
for (size_t j = 1; argv[i][j] != '\0'; j++)
{
if (argv[i][j] == 'n')
newline = false;
else if (argv[i][j] == 'e')
interpretEscapes = true;
else if (argv[i][j] == 'E')
interpretEscapes = false;
else
goto printArgs;
}
argStart++;
}
else
break;
}
}
printArgs:
for (int i = argStart; i < argc; i++)
{
if (interpretEscapes)
PrintEscaped(argv[i]);
else
fputs(argv[i], stdout);
if (i < argc - 1)
putchar(' ');
}
if (newline)
putchar('\n');
return 0;
}

View File

@ -0,0 +1,877 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <pwd.h>
#include <coreutils.h>
#define MAX_LINE_LEN 1024
#define MAX_HISTORY 128
#define CTRL_KEY(k) ((k) & 0x1F)
#define MAX_COMPLETIONS 128
typedef struct
{
char *items[MAX_HISTORY];
int count;
int Index;
} History;
typedef enum
{
MODE_INSERT,
MODE_COMMAND
} InputMode;
typedef struct
{
char line[MAX_LINE_LEN];
int cursor;
int length;
InputMode mode;
History history;
struct termios origTermios;
char prompt[PATH_MAX + 128];
int promptLength;
} ShellState;
typedef struct
{
char *items[MAX_COMPLETIONS];
int count;
} CompletionList;
static ShellState GlobalShellState;
static int progIsFsh = 0;
void DisableRawMode(ShellState *state);
void SaveHistory(ShellState *state);
void InitializeShell(ShellState *state);
void FreeCompletionList(CompletionList *list);
CompletionList GetCompletions(const char *partial);
void DisplayCompletions(ShellState *state, CompletionList *list);
void UpdatePrompt(ShellState *state);
int GetVisibleLength(const char *str);
void CleanupAndExit(int code)
{
SaveHistory(&GlobalShellState);
DisableRawMode(&GlobalShellState);
exit(code);
}
void HandleSignalInterrupt(int sig)
{
(void)sig;
write(STDOUT_FILENO, "\n\r", 2);
CleanupAndExit(130);
}
void EnableRawMode(ShellState *state)
{
tcgetattr(STDIN_FILENO, &state->origTermios);
struct termios raw = state->origTermios;
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
raw.c_oflag &= ~(OPOST);
raw.c_cflag |= (CS8);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
raw.c_cc[VMIN] = 1;
raw.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
void DisableRawMode(ShellState *state)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &state->origTermios);
}
void AddHistory(ShellState *state, const char *line)
{
if (!line || strlen(line) == 0)
return;
char *newEntry = strdup(line);
if (!newEntry)
return;
if (state->history.count < MAX_HISTORY)
state->history.items[state->history.count++] = newEntry;
else
{
free(state->history.items[0]);
memmove(state->history.items, state->history.items + 1,
(MAX_HISTORY - 1) * sizeof(char *));
state->history.items[MAX_HISTORY - 1] = newEntry;
}
state->history.Index = state->history.count;
SaveHistory(state);
}
void LoadHistory(ShellState *state)
{
char *home = getenv("HOME");
if (!home)
return;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/.fsh_history", home);
FILE *fp = fopen(path, "r");
if (!fp)
return;
char **tmpHistory = malloc(MAX_HISTORY * sizeof(char *));
int tmpCount = 0;
char line[MAX_LINE_LEN];
while (fgets(line, sizeof(line), fp))
{
size_t len = strlen(line);
if (len > 0 && line[len - 1] == '\n')
line[len - 1] = '\0';
if (strlen(line) > 0)
{
if (tmpCount < MAX_HISTORY)
tmpHistory[tmpCount++] = strdup(line);
else
{
free(tmpHistory[0]);
memmove(tmpHistory, tmpHistory + 1, (MAX_HISTORY - 1) * sizeof(char *));
tmpHistory[MAX_HISTORY - 1] = strdup(line);
}
}
}
fclose(fp);
for (int i = 0; i < tmpCount; i++)
state->history.items[i] = tmpHistory[i];
state->history.count = tmpCount;
state->history.Index = tmpCount;
free(tmpHistory);
}
void SaveHistory(ShellState *state)
{
char *home = getenv("HOME");
if (!home)
return;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/.fsh_history", home);
int fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0600);
if (fd < 0)
return;
struct flock fl = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = 0,
.l_len = 0};
if (fcntl(fd, F_SETLKW, &fl) == -1)
{
close(fd);
return;
}
if (state->history.count > 0)
{
int last = state->history.count - 1;
if (state->history.items[last])
{
char *cmd = state->history.items[last];
write(fd, cmd, strlen(cmd));
write(fd, "\n", 1);
}
}
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl);
close(fd);
}
void ProcessViCommand(ShellState *state, char c)
{
switch (c)
{
case 'h':
if (state->cursor > 0)
state->cursor--;
break;
case 'l':
if (state->cursor < state->length)
state->cursor++;
break;
case 'k':
if (state->history.Index > 0)
{
state->history.Index--;
strncpy(state->line, state->history.items[state->history.Index], MAX_LINE_LEN);
state->length = strlen(state->line);
state->cursor = state->length;
}
break;
case 'j':
if (state->history.Index < state->history.count - 1)
{
state->history.Index++;
strncpy(state->line, state->history.items[state->history.Index], MAX_LINE_LEN);
state->length = strlen(state->line);
state->cursor = state->length;
}
break;
case 'i':
state->mode = MODE_INSERT;
break;
case 27:
state->mode = MODE_COMMAND;
break;
}
}
void FreeCompletionList(CompletionList *list)
{
for (int i = 0; i < list->count; i++)
free(list->items[i]);
list->count = 0;
}
CompletionList GetCompletions(const char *partial)
{
CompletionList list = {0};
char *path = getenv("PATH");
if (!path)
return list;
char *pathCopy = strdup(path);
char *dir = strtok(pathCopy, ":");
while (dir && list.count < MAX_COMPLETIONS)
{
DIR *d = opendir(dir);
if (!d)
{
dir = strtok(NULL, ":");
continue;
}
struct dirent *entry;
while ((entry = readdir(d)) && list.count < MAX_COMPLETIONS)
{
if (strncmp(entry->d_name, partial, strlen(partial)) == 0)
{
char fullPath[PATH_MAX];
snprintf(fullPath, sizeof(fullPath), "%s/%s", dir, entry->d_name);
struct stat st;
if (stat(fullPath, &st) == 0 && (st.st_mode & S_IXUSR))
list.items[list.count++] = strdup(entry->d_name);
}
}
closedir(d);
dir = strtok(NULL, ":");
}
free(pathCopy);
return list;
}
void DisplayCompletions(ShellState *state, CompletionList *list)
{
if (list->count == 0)
return;
write(STDOUT_FILENO, "\n\r", 2);
for (int i = 0; i < list->count; i++)
{
write(STDOUT_FILENO, list->items[i], strlen(list->items[i]));
write(STDOUT_FILENO, " ", 2);
}
write(STDOUT_FILENO, "\n\r", 2);
write(STDOUT_FILENO, state->prompt, strlen(state->prompt));
write(STDOUT_FILENO, state->line, state->length);
}
void ReadLine(ShellState *state)
{
state->length = 0;
state->cursor = 0;
state->line[0] = '\0';
state->mode = MODE_INSERT;
UpdatePrompt(state);
write(STDOUT_FILENO, "\r", 1);
write(STDOUT_FILENO, state->prompt, strlen(state->prompt));
EnableRawMode(state);
while (1)
{
char c;
ssize_t nread = read(STDIN_FILENO, &c, 1);
if (nread <= 0)
continue;
if (state->mode == MODE_COMMAND)
ProcessViCommand(state, c);
else
{
if (c == '\t')
{
char *wordStart = state->line;
for (int i = state->cursor - 1; i >= 0; i--)
{
if (state->line[i] == ' ')
{
wordStart = &state->line[i + 1];
break;
}
}
char partial[MAX_LINE_LEN];
int len = state->cursor - (wordStart - state->line);
strncpy(partial, wordStart, len);
partial[len] = '\0';
CompletionList completions = GetCompletions(partial);
if (completions.count == 1)
{
int restLength = strlen(completions.items[0]) - len;
if (restLength > 0)
{
memmove(&state->line[state->cursor + restLength],
&state->line[state->cursor],
state->length - state->cursor + 1);
memcpy(&state->line[state->cursor],
&completions.items[0][len],
restLength);
state->cursor += restLength;
state->length += restLength;
}
}
else if (completions.count > 1)
{
int prefixLength = len;
int canExtend = 1;
while (canExtend)
{
char nextChar = completions.items[0][prefixLength];
if (nextChar == '\0')
break;
for (int i = 1; i < completions.count; i++)
{
if (completions.items[i][prefixLength] != nextChar)
{
canExtend = 0;
break;
}
}
if (canExtend)
prefixLength++;
}
if (prefixLength > len)
{
int restLength = prefixLength - len;
memmove(&state->line[state->cursor + restLength],
&state->line[state->cursor],
state->length - state->cursor + 1);
memcpy(&state->line[state->cursor],
&completions.items[0][len],
restLength);
state->cursor += restLength;
state->length += restLength;
}
DisplayCompletions(state, &completions);
}
FreeCompletionList(&completions);
continue;
}
else if (c == 0x1B)
{
char seq[3];
if (read(STDIN_FILENO, &seq[0], 1) != 1)
continue;
if (read(STDIN_FILENO, &seq[1], 1) != 1)
continue;
if (seq[0] == '[')
{
switch (seq[1])
{
case 'A':
if (state->history.Index > 0)
{
state->history.Index--;
strncpy(state->line, state->history.items[state->history.Index], MAX_LINE_LEN - 1);
state->length = strlen(state->line);
state->cursor = state->length;
}
break;
case 'B':
if (state->history.Index < state->history.count)
{
state->history.Index++;
if (state->history.Index == state->history.count)
{
state->line[0] = '\0';
state->length = 0;
state->cursor = 0;
}
else
{
strncpy(state->line, state->history.items[state->history.Index], MAX_LINE_LEN - 1);
state->length = strlen(state->line);
state->cursor = state->length;
}
}
break;
case 'C':
if (state->cursor < state->length)
state->cursor++;
break;
case 'D':
if (state->cursor > 0)
state->cursor--;
break;
case 'H':
state->cursor = 0;
break;
case 'F':
state->cursor = state->length;
break;
case '3':
{
if (read(STDIN_FILENO, &seq[2], 1) != 1)
continue;
if (seq[2] == '~' && state->cursor < state->length)
{
memmove(&state->line[state->cursor], &state->line[state->cursor + 1],
state->length - state->cursor);
state->length--;
}
break;
}
}
}
else if (seq[0] == 'O')
{
switch (seq[1])
{
case 'H':
state->cursor = 0;
break;
case 'F':
state->cursor = state->length;
break;
}
}
}
else if (c == CTRL_KEY('c'))
{
write(STDOUT_FILENO, "\n\r", 2);
write(STDOUT_FILENO, state->prompt, strlen(state->prompt));
state->length = 0;
state->cursor = 0;
state->line[0] = '\0';
}
else if (c == '\r' || c == '\n')
{
write(STDOUT_FILENO, "\n", 1);
state->line[state->length] = '\0';
DisableRawMode(state);
if (state->length > 0)
{
AddHistory(state, state->line);
state->history.Index = state->history.count;
}
return;
}
else if (c == 0x7F)
{
if (state->cursor > 0)
{
memmove(&state->line[state->cursor - 1], &state->line[state->cursor],
state->length - state->cursor + 1);
state->cursor--;
state->length--;
}
}
else if (c == CTRL_KEY('d') && state->length == 0)
{
write(STDOUT_FILENO, "\n", 1);
DisableRawMode(state);
exit(EXIT_SUCCESS);
}
else if (isprint(c) && state->length < MAX_LINE_LEN - 1)
{
memmove(&state->line[state->cursor + 1], &state->line[state->cursor],
state->length - state->cursor + 1);
state->line[state->cursor] = c;
state->cursor++;
state->length++;
}
}
write(STDOUT_FILENO, "\r", 1);
write(STDOUT_FILENO, "\x1b[K", 3);
write(STDOUT_FILENO, state->prompt, strlen(state->prompt));
write(STDOUT_FILENO, state->line, state->length);
int promptVisibleLength = GetVisibleLength(state->prompt);
char buf[32];
snprintf(buf, sizeof(buf), "\r\x1b[%dC", promptVisibleLength + state->cursor);
write(STDOUT_FILENO, buf, strlen(buf));
}
}
int GetVisibleLength(const char *str)
{
int len = 0;
int inEscape = 0;
while (*str)
{
if (*str == '\x1b')
inEscape = 1;
else if (inEscape)
{
if ((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z'))
inEscape = 0;
}
else
len++;
str++;
}
return len;
}
void UpdatePrompt(ShellState *state)
{
char hostname[256] = {0};
gethostname(hostname, sizeof(hostname));
struct passwd *pw = getpwuid(getuid());
char *username = pw ? pw->pw_name : "user";
char cwd[PATH_MAX];
if (!getcwd(cwd, sizeof(cwd)))
strcpy(cwd, "~");
if (pw && pw->pw_dir && strncmp(cwd, pw->pw_dir, strlen(pw->pw_dir)) == 0)
{
size_t home_len = strlen(pw->pw_dir);
if (strlen(cwd) == home_len)
strcpy(cwd, "~");
else if (cwd[home_len] == '/')
{
memmove(cwd + 1, cwd + home_len, strlen(cwd) - home_len + 1);
cwd[0] = '~';
}
}
char *customPrompt = getenv("SHELL_PROMPT");
if (customPrompt)
{
snprintf(state->prompt, sizeof(state->prompt), "%s", customPrompt);
}
else
{
// snprintf(state->prompt, sizeof(state->prompt),
// "\x1b[;32m┌──(%s@%s)-[\x1b[0;1m%s\x1b[;32m]\n\r└─\x1b[;32m$\x1b[00m ",
// username, hostname, cwd);
// snprintf(state->prompt, sizeof(state->prompt),
// "\x1b[;32m%s@%s\x1b[0;1m:\x1b[01;34m%s\x1b[0;1m$\x1b[00m ",
// username, hostname, cwd);
if (progIsFsh)
{
snprintf(state->prompt, sizeof(state->prompt),
"\x1b[1;34m%s\x1b[0;1m:\x1b[01;35m%s\x1b[0;1m$\x1b[00m ",
username, cwd);
}
else
{
snprintf(state->prompt, sizeof(state->prompt),
"$ ");
}
}
state->promptLength = GetVisibleLength(state->prompt);
}
void ExecuteCommand(char **args)
{
if (!args[0])
return;
for (int i = 0; args[i] != NULL; i++)
{
char *arg = args[i];
size_t len = strlen(arg);
if (len >= 2 && arg[0] == '"' && arg[len - 1] == '"')
{
arg[len - 1] = '\0';
memmove(arg, arg + 1, len - 1);
}
}
if (strcmp(args[0], "exit") == 0)
exit(0);
else if (strcmp(args[0], "cd") == 0)
{
char *targetDirectory = args[1];
if (!targetDirectory || strcmp(targetDirectory, "~") == 0)
{
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir)
targetDirectory = pw->pw_dir;
else
{
fprintf(stderr, "cd: HOME not set and no password directory available\n");
return;
}
}
else if (targetDirectory[0] == '~')
{
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir)
{
char newPath[PATH_MAX];
snprintf(newPath, sizeof(newPath), "%s%s", pw->pw_dir, targetDirectory + 1);
targetDirectory = newPath;
}
}
if (chdir(targetDirectory))
perror("cd");
else
UpdatePrompt(&GlobalShellState);
return;
}
pid_t pid = fork();
if (pid == 0)
{
struct termios term;
tcgetattr(STDIN_FILENO, &term);
term.c_lflag |= (ECHO | ICANON | IEXTEN | ISIG);
term.c_oflag |= (OPOST | ONLCR);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
write(STDOUT_FILENO, "\r", 1);
execvp(args[0], args);
if (errno == ENOENT)
{
write(STDERR_FILENO, "\r", 1);
fprintf(stderr, "%s: command not found\n", args[0]);
}
else
{
write(STDERR_FILENO, "\r", 1);
perror(args[0]);
}
exit(EXIT_FAILURE);
}
else if (pid > 0)
{
int status;
waitpid(pid, &status, 0);
write(STDOUT_FILENO, "\r\n", 2);
}
else
perror("fork");
}
void ShellLoop(ShellState *state)
{
signal(SIGINT, HandleSignalInterrupt);
LoadHistory(state);
while (1)
{
ReadLine(state);
if (state->length == 0)
continue;
char *trimmed = state->line;
while (*trimmed && isspace(*trimmed))
trimmed++;
char *end = trimmed + strlen(trimmed) - 1;
while (end > trimmed && isspace(*end))
*end-- = '\0';
if (*trimmed == '\0')
continue;
memmove(state->line, trimmed, strlen(trimmed) + 1);
state->length = strlen(state->line);
char *args[MAX_LINE_LEN / 2 + 1];
int i = 0;
char *p = state->line;
int inQuotes = 0;
char *start = p;
while (*p)
{
if (*p == '"')
inQuotes = !inQuotes;
else if ((*p == ' ' || *p == '\t') && !inQuotes)
{
if (p > start)
{
*p = '\0';
args[i++] = start;
}
start = p + 1;
}
p++;
}
if (p > start)
args[i++] = start;
args[i] = NULL;
if (i > 0)
ExecuteCommand(args);
}
}
void InitializeShell(ShellState *state)
{
memset(state, 0, sizeof(ShellState));
UpdatePrompt(state);
LoadHistory(state);
signal(SIGINT, HandleSignalInterrupt);
printf("\x1b[01;35mFennix Shell v%s\n\r", PROGRAM_VERSION);
printf("\x1b[;31mEarly development version!\x1b[0m\n\r");
}
void DisableRawModeAtExit(void)
{
DisableRawMode(&GlobalShellState);
}
void PrintHelp()
{
printf("Usage: sh [OPTION]... [SCRIPT]\n");
printf("A simple shell implementation.\n\n");
printf("Options:\n");
printf(" -c COMMAND execute COMMAND and exit\n");
printf(" --help display this help and exit\n");
printf(" --version output version information and exit\n\n");
printf("If SCRIPT is provided, execute commands from the script file.\n");
printf("Otherwise, run in interactive mode.\n\n");
printf("Environment variables:\n");
printf(" SHELL_PROMPT custom prompt format (default: user@host:path$ )\n");
}
int main(int argc, char *argv[])
{
if (argc > 1)
{
if (strcmp(argv[1], "--help") == 0)
{
PrintHelp();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[1], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
}
char *basename = strrchr(argv[0], '/');
if (basename == NULL)
basename = argv[0];
else
basename++;
if (strcmp(basename, "fsh") == 0)
progIsFsh = 1;
memset(&GlobalShellState, 0, sizeof(ShellState));
InitializeShell(&GlobalShellState);
signal(SIGINT, HandleSignalInterrupt);
atexit(DisableRawModeAtExit);
if (argc > 1)
{
if (strcmp(argv[1], "-c") == 0)
ExecuteCommand(&argv[2]);
else
{
FILE *fp = fopen(argv[1], "r");
if (!fp)
{
perror("fopen");
CleanupAndExit(EXIT_FAILURE);
}
char line[MAX_LINE_LEN];
while (fgets(line, sizeof(line), fp))
{
line[strcspn(line, "\n")] = '\0';
char *args[] = {"/bin/sh", "-c", line, NULL};
ExecuteCommand(args);
}
fclose(fp);
}
}
else
ShellLoop(&GlobalShellState);
CleanupAndExit(EXIT_SUCCESS);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,138 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int TestFile(const char *path, char mode)
{
struct stat st;
if (stat(path, &st) != 0)
return 1;
switch (mode)
{
case 'b':
return S_ISBLK(st.st_mode) ? 0 : 1;
case 'c':
return S_ISCHR(st.st_mode) ? 0 : 1;
case 'd':
return S_ISDIR(st.st_mode) ? 0 : 1;
case 'e':
return 0;
case 'f':
return S_ISREG(st.st_mode) ? 0 : 1;
case 'g':
return (st.st_mode & S_ISGID) ? 0 : 1;
case 'h':
case 'L':
return lstat(path, &st) == 0 && S_ISLNK(st.st_mode) ? 0 : 1;
case 'p':
return S_ISFIFO(st.st_mode) ? 0 : 1;
case 'r':
return access(path, R_OK) == 0 ? 0 : 1;
case 's':
return st.st_size > 0 ? 0 : 1;
case 'u':
return (st.st_mode & S_ISUID) ? 0 : 1;
case 'w':
return access(path, W_OK) == 0 ? 0 : 1;
case 'x':
return access(path, X_OK) == 0 ? 0 : 1;
default:
return 2;
}
}
int TestString(const char *s1, const char *op, const char *s2)
{
if (!strcmp(op, "="))
return strcmp(s1, s2) == 0 ? 0 : 1;
if (!strcmp(op, "!="))
return strcmp(s1, s2) != 0 ? 0 : 1;
if (!strcmp(op, "<"))
return strcmp(s1, s2) < 0 ? 0 : 1;
if (!strcmp(op, ">"))
return strcmp(s1, s2) > 0 ? 0 : 1;
return 2;
}
int TestInteger(const char *n1, const char *op, const char *n2)
{
int i1 = atoi(n1), i2 = atoi(n2);
if (!strcmp(op, "-eq"))
return i1 == i2 ? 0 : 1;
if (!strcmp(op, "-ne"))
return i1 != i2 ? 0 : 1;
if (!strcmp(op, "-gt"))
return i1 > i2 ? 0 : 1;
if (!strcmp(op, "-ge"))
return i1 >= i2 ? 0 : 1;
if (!strcmp(op, "-lt"))
return i1 < i2 ? 0 : 1;
if (!strcmp(op, "-le"))
return i1 <= i2 ? 0 : 1;
return 2;
}
int main(int argc, char *argv[])
{
char *base = strrchr(argv[0], '/');
base = base ? base + 1 : argv[0];
int isBracketForm = (strcmp(base, "[") == 0);
if (isBracketForm)
{
if (argc < 2 || strcmp(argv[argc - 1], "]") != 0)
{
fprintf(stderr, "Error: missing closing bracket ']'.\n");
return 2;
}
argc--;
}
if (argc == 1)
return 1;
if (argc == 2)
return argv[1][0] ? 0 : 1;
if (argc == 3)
{
if (!strcmp(argv[1], "!"))
return argv[2][0] ? 1 : 0;
return TestFile(argv[2], argv[1][1]);
}
if (argc == 4)
{
if (!strcmp(argv[1], "!"))
return !main(3, &argv[1]);
if (strchr("=!<>", argv[2][0]))
return TestString(argv[1], argv[2], argv[3]);
return TestInteger(argv[1], argv[2], argv[3]);
}
return 2;
}

View File

@ -0,0 +1,260 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <coreutils.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <sys/utsname.h>
typedef union
{
struct
{
uint8_t kernelName : 1;
uint8_t nodeName : 1;
uint8_t kernelRelease : 1;
uint8_t kernelVersion : 1;
uint8_t machine : 1;
uint8_t processor : 1;
uint8_t hardwarePlatform : 1;
uint8_t operatingSystem : 1;
};
uint8_t raw;
} UnameFlags;
const char *GetOperatingSystemName(const char *systemName)
{
if (strcmp(systemName, "Fennix") == 0)
return "Fennix";
if (strncmp(systemName, "Linux", 5) == 0)
return "GNU/Linux";
if (strncmp(systemName, "Darwin", 6) == 0)
return "macOS";
if (strncmp(systemName, "FreeBSD", 7) == 0)
return "FreeBSD";
if (strncmp(systemName, "NetBSD", 6) == 0)
return "NetBSD";
if (strncmp(systemName, "OpenBSD", 7) == 0)
return "OpenBSD";
if (strncmp(systemName, "DragonFly", 9) == 0)
return "DragonFly BSD";
if (strncmp(systemName, "SunOS", 5) == 0)
return "SunOS";
if (strncmp(systemName, "AIX", 3) == 0)
return "AIX";
if (strncmp(systemName, "HP-UX", 5) == 0)
return "HP-UX";
if (strncmp(systemName, "GNU", 3) == 0)
return "GNU";
if (strncmp(systemName, "Minix", 5) == 0)
return "Minix";
if (strncmp(systemName, "QNX", 3) == 0)
return "QNX";
if (strncmp(systemName, "Haiku", 5) == 0)
return "Haiku";
if (strncmp(systemName, "OS/2", 4) == 0)
return "OS/2";
return systemName;
}
const char *GetProcessorType(const char *machine)
{
if (strcmp(machine, "x86_64") == 0)
return "x86_64";
if (strcmp(machine, "i386") == 0)
return "i386";
if (strcmp(machine, "i686") == 0)
return "i686";
if (strncmp(machine, "arm", 3) == 0)
return "arm";
if (strncmp(machine, "aarch64", 7) == 0)
return "aarch64";
if (strncmp(machine, "riscv64", 7) == 0)
return "riscv64";
if (strncmp(machine, "mips", 4) == 0)
return "mips";
if (strncmp(machine, "powerpc", 7) == 0)
return "powerpc";
if (strncmp(machine, "sparc", 5) == 0)
return "sparc";
return "unknown";
}
const char *GetHardwarePlatform(const char *machine)
{
if (strcmp(machine, "x86_64") == 0)
return "x86_64";
if (strcmp(machine, "i686") == 0 || strcmp(machine, "i386") == 0)
return "pc";
if (strncmp(machine, "arm", 3) == 0)
return "arm";
if (strncmp(machine, "aarch64", 7) == 0)
return "aarch64";
if (strncmp(machine, "riscv64", 7) == 0)
return "riscv64";
if (strncmp(machine, "mips", 4) == 0)
return "mips";
if (strncmp(machine, "powerpc64le", 11) == 0)
return "ppc64le";
if (strncmp(machine, "powerpc", 7) == 0)
return "powerpc";
if (strncmp(machine, "sparc", 5) == 0)
return "sparc";
return "unknown";
}
void PrintUsage()
{
printf("Usage: uname [OPTION]...\n");
printf("Display specific system information. With no OPTION, defaults to -s.\n\n");
printf(" -a, --all display all information, in the following order,\n");
printf(" except omit -p and -i if unknown:\n");
printf(" -s, --kernel-name display the kernel name\n");
printf(" -n, --nodename display the network node hostname\n");
printf(" -r, --kernel-release display the kernel release\n");
printf(" -v, --kernel-version display the kernel version\n");
printf(" -m, --machine display the machine hardware name\n");
printf(" -p, --processor display the processor type (non-portable)\n");
printf(" -i, --hardware-platform display the hardware platform (non-portable)\n");
printf(" -o, --operating-system display the operating system\n");
printf(" --help show this help message and exit\n");
printf(" --version output version information and exit\n");
}
int main(int argc, char *argv[])
{
struct utsname buffer;
if (uname(&buffer) != 0)
{
perror("uname");
exit(EXIT_FAILURE);
}
if (argc == 1)
{
printf("%s\n", buffer.sysname);
return 0;
}
UnameFlags flags = {0};
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
{
flags.raw = 0xFF;
break;
}
else if (argv[i][0] == '-' && argv[i][1] != '\0')
{
for (size_t j = 1; j < strlen(argv[i]); j++)
{
switch (argv[i][j])
{
case 's':
flags.kernelName = 1;
break;
case 'n':
flags.nodeName = 1;
break;
case 'r':
flags.kernelRelease = 1;
break;
case 'v':
flags.kernelVersion = 1;
break;
case 'm':
flags.machine = 1;
break;
case 'p':
flags.processor = 1;
break;
case 'i':
flags.hardwarePlatform = 1;
break;
case 'o':
flags.operatingSystem = 1;
break;
default:
fprintf(stderr, "uname: invalid option -- '%c'\n", argv[i][j]);
PrintUsage();
exit(EXIT_FAILURE);
}
}
}
else if (strcmp(argv[i], "--kernel-name") == 0)
flags.kernelName = 1;
else if (strcmp(argv[i], "--nodename") == 0)
flags.nodeName = 1;
else if (strcmp(argv[i], "--kernel-release") == 0)
flags.kernelRelease = 1;
else if (strcmp(argv[i], "--kernel-version") == 0)
flags.kernelVersion = 1;
else if (strcmp(argv[i], "--machine") == 0)
flags.machine = 1;
else if (strcmp(argv[i], "--processor") == 0)
flags.processor = 1;
else if (strcmp(argv[i], "--hardware-platform") == 0)
flags.hardwarePlatform = 1;
else if (strcmp(argv[i], "--operating-system") == 0)
flags.operatingSystem = 1;
else if (strcmp(argv[i], "--help") == 0)
{
PrintUsage();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[i], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
else
{
fprintf(stderr, "uname: invalid option -- '%s'\n", argv[i]);
PrintUsage();
exit(EXIT_FAILURE);
}
}
bool first = true;
#define PRINT_IF(flag, value) \
if (flags.flag) \
{ \
if (!first) \
putchar(' '); \
printf("%s", value); \
first = false; \
}
PRINT_IF(kernelName, buffer.sysname);
PRINT_IF(nodeName, buffer.nodename);
PRINT_IF(kernelRelease, buffer.release);
PRINT_IF(kernelVersion, buffer.version);
PRINT_IF(machine, buffer.machine);
PRINT_IF(processor, GetProcessorType(buffer.machine));
PRINT_IF(hardwarePlatform, GetHardwarePlatform(buffer.machine));
PRINT_IF(operatingSystem, GetOperatingSystemName(buffer.sysname));
putchar('\n');
return 0;
}

2
Userspace/docker/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
cache/*
docker-root/*

View File

@ -0,0 +1,3 @@
FROM scratch
ADD docker-root /
CMD ["/bin/sh"]

68
Userspace/docker/Makefile Normal file
View File

@ -0,0 +1,68 @@
export DOCKER_ROOT = $(CURDIR)/docker-root
DOCKER_IMAGE_NAME = fennix-userspace
export CMAKE_INSTALL_PREFIX := $(DOCKER_ROOT)
export CMAKE_SYSROOT := $(DOCKER_ROOT)
export LDFLAGS := --sysroot=$(DOCKER_ROOT) \
-ggdb3 -O0
export CFLAGS := \
--sysroot=$(DOCKER_ROOT) \
-I$(DOCKER_ROOT)/include \
-DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
create_docker_out:
rm -rf cache
rm -rf $(DOCKER_ROOT)
mkdir -p $(DOCKER_ROOT)
mkdir -p $(DOCKER_ROOT)/bin
mkdir -p $(DOCKER_ROOT)/etc
mkdir -p $(DOCKER_ROOT)/lib
mkdir -p $(DOCKER_ROOT)/lib64
mkdir -p $(DOCKER_ROOT)/include/linux
mkdir -p $(DOCKER_ROOT)/usr/bin
mkdir -p $(DOCKER_ROOT)/usr/share/doc
mkdir -p $(DOCKER_ROOT)/usr/share/info
mkdir -p $(DOCKER_ROOT)/usr/include
mkdir -p $(DOCKER_ROOT)/usr/lib
build_docker_coreutils:
mkdir -p cache/coreutils
cd cache/coreutils && \
cmake $(CURDIR)/../coreutils \
-DCMAKE_INSTALL_PREFIX:PATH=$(DOCKER_ROOT) \
-DCMAKE_SYSROOT=$(DOCKER_ROOT) \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(DOCKER_ROOT)/include \
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$(DOCKER_ROOT)/include \
&& \
make -j$(shell nproc) && \
make install
build_docker_libc:
mkdir -p cache/libc
cd cache/libc && \
cmake $(CURDIR)/../libc \
-DCMAKE_INSTALL_PREFIX=$(DOCKER_ROOT) \
-DCMAKE_SYSROOT=$(DOCKER_ROOT) \
-DCMAKE_INSTALL_INCLUDEDIR=include \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_INSTALL_BINDIR=bin && \
make -j$(shell nproc) && \
make install
docker_image:
docker build -t $(DOCKER_IMAGE_NAME) -f Dockerfile .
docker_run:
@echo "Running container..."
@docker run -it --name fennix-userspace-instance fennix-userspace:latest /bin/sh || true
@echo "\nExit code: $$(docker inspect fennix-userspace-instance --format='{{.State.ExitCode}}')"
@docker rm fennix-userspace-instance >/dev/null 2>&1
docker: create_docker_out
$(MAKE) build_docker_libc
$(MAKE) build_docker_coreutils
clean:
rm -rf cache
rm -rf $(DOCKER_ROOT)

1
Userspace/libc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,27 @@
{
"C Library License": {
"isFileTemplate": true,
"prefix": [
"license",
],
"body": [
"/*",
"\tThis file is part of Fennix C Library.",
"",
"\tFennix C Library is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix C Library is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create libc license."
}
}

View File

@ -0,0 +1,144 @@
cmake_minimum_required(VERSION 3.10)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
project(FennixCLibrary VERSION 0.0.1)
if(NOT DEFINED ENV{WORKSPACE_DIR})
set(STANDALONE_BUILD ON)
message(STATUS "Compiling standalone")
if(NOT DEFINED ENV{CMAKE_INSTALL_PREFIX})
set(CMAKE_INSTALL_PREFIX "/usr")
message(STATUS "Using default install prefix: /usr")
else()
message(STATUS "Using custom install prefix: $ENV{CMAKE_INSTALL_PREFIX}")
endif()
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
if(NOT DEFINED ENV{CMAKE_INSTALL_PREFIX})
set(CMAKE_INSTALL_PREFIX "$ENV{WORKSPACE_DIR}/out")
message(STATUS "Using default install prefix: $ENV{WORKSPACE_DIR}/out")
else()
message(STATUS "Using custom install prefix: $ENV{CMAKE_INSTALL_PREFIX}")
endif()
try_compile(
WORKSPACE_TEST
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/workspace_test.c
CMAKE_FLAGS "-DCMAKE_C_COMPILER=$ENV{CC} -DCMAKE_CXX_COMPILER=$ENV{CXX} -DCMAKE_ASM_COMPILER=$ENV{AS} -DCMAKE_AR=$ENV{AR} -DCMAKE_LINKER=$ENV{LD}"
OUTPUT_VARIABLE OUTPUT
)
if(NOT WORKSPACE_TEST)
message(FATAL_ERROR "Workspace test failed: ${OUTPUT}")
else()
message(STATUS "Workspace test passed")
endif()
endif()
if(NOT DEFINED TARGET_OS)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(TARGET_OS "linux")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Fennix")
set(TARGET_OS "fennix")
else()
message(FATAL_ERROR "Unsupported OS: ${CMAKE_SYSTEM_NAME}")
endif()
endif()
if(NOT DEFINED TARGET_ARCH)
set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
message(STATUS "Building for ${TARGET_OS}/${TARGET_ARCH}")
if(DEFINED ENV{CC})
set(CMAKE_C_COMPILER "$ENV{CC}")
endif()
if(DEFINED ENV{CXX})
set(CMAKE_CXX_COMPILER "$ENV{CXX}")
endif()
if(DEFINED ENV{AS})
set(CMAKE_ASM_COMPILER "$ENV{AS}")
endif()
if(DEFINED ENV{AR})
set(CMAKE_AR "$ENV{AR}")
endif()
if(DEFINED ENV{LD})
set(CMAKE_LINKER "$ENV{LD}")
endif()
if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
else()
set(CMAKE_C_FLAGS "-O2")
endif()
set(SYSDEPS_DIR ${CMAKE_SOURCE_DIR}/sysdeps)
set(ABIS_DIR ${CMAKE_SOURCE_DIR}/abis)
set(SYSDEPS_GENERIC ${SYSDEPS_DIR}/${TARGET_OS}/generic)
set(SYSDEPS_PATH ${SYSDEPS_DIR}/${TARGET_OS}/${TARGET_ARCH})
set(ABIS_GENERIC ${ABIS_DIR}/${TARGET_OS}/generic)
set(ABIS_PATH ${ABIS_DIR}/${TARGET_OS}/${TARGET_ARCH})
if(NOT EXISTS ${SYSDEPS_PATH} AND NOT EXISTS ${SYSDEPS_GENERIC})
message(FATAL_ERROR "Missing sysdeps for ${TARGET_OS}: ${SYSDEPS_PATH} or ${SYSDEPS_GENERIC}")
endif()
if(NOT EXISTS ${ABIS_PATH} AND NOT EXISTS ${ABIS_GENERIC})
message(FATAL_ERROR "Missing abis for ${TARGET_OS}: ${ABIS_PATH} or ${ABIS_GENERIC}")
endif()
message(STATUS "Using sysdeps from: ${SYSDEPS_GENERIC} and ${SYSDEPS_PATH}")
message(STATUS "Using abis from: ${ABIS_GENERIC} and ${ABIS_PATH}")
include_directories(${ABIS_GENERIC} ${ABIS_PATH})
include_directories(${CMAKE_SOURCE_DIR}/include)
add_subdirectory(runtime)
add_subdirectory(interpreter)
add_subdirectory(src)
add_subdirectory(libs)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include
FILES_MATCHING
PATTERN "*")
install(DIRECTORY ${ABIS_GENERIC}/
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/
FILES_MATCHING
PATTERN "*")
install(DIRECTORY ${ABIS_PATH}/
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/
FILES_MATCHING
PATTERN "*")
if(TARGET_OS STREQUAL "Linux")
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
/lib/ld.so
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib/ld-linux-x86-64.so.2\"
)")
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
/lib/ld.so
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib64/ld-linux-x86-64.so.2\"
)")
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
/lib/libc.so
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib/libc.so.6\"
)")
install(CODE "execute_process(
COMMAND ${CMAKE_COMMAND} -E create_symlink
/lib/libc.so
\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib64/libc.so.6\"
)")
endif()

View File

@ -1,12 +0,0 @@
build:
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/errno.h $(CURDIR)/include/errno.h
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/syscalls.h $(CURDIR)/include/fennix/syscalls.h
cp -a $(CURDIR)/include/. $(WORKSPACE_DIR)/out/include
make -C interpreter build
make -C runtime build
make -C src build
clean:
make -C interpreter clean
make -C runtime clean
make -C src clean

View File

View File

@ -0,0 +1,591 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_ERRNO_H__
#define __FENNIX_API_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
/**
* No Error
*/
#define EOK 0
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
#define E2BIG 1
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
#define EACCES 2
/**
* Address in use. The specified address is in use.
*/
#define EADDRINUSE 3
/**
* Address not available. The specified address is not available from
* the local system.
*/
#define EADDRNOTAVAIL 4
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
#define EAFNOSUPPORT 5
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
#define EAGAIN 6
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
#define EALREADY 7
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
#define EBADF 8
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
#define EBADMSG 9
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
#define EBUSY 10
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
#define ECANCELED 11
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
#define ECHILD 12
/**
* Connection aborted. The connection has been aborted.
*/
#define ECONNABORTED 13
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
#define ECONNREFUSED 14
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
#define ECONNRESET 15
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
#define EDEADLK 16
/**
* Destination address required. No bind address was established.
*/
#define EDESTADDRREQ 17
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
#define EDOM 18
/**
* Reserved.
*/
#define EDQUOT 19
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
#define EEXIST 20
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
#define EFAULT 21
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
#define EFBIG 22
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
#define EHOSTUNREACH 23
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
#define EIDRM 24
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
#define EILSEQ 25
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
#define EINPROGRESS 26
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
#define EINTR 27
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
#define EINVAL 28
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
#define EIO 29
/**
* Socket is connected. The specified socket is already connected.
*/
#define EISCONN 30
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
#define EISDIR 31
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
#define ELOOP 32
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
#define EMFILE 33
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
#define EMLINK 34
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
#define EMSGSIZE 35
/**
* Reserved.
*/
#define EMULTIHOP 36
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
#define ENAMETOOLONG 37
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
#define ENETDOWN 38
/**
* The connection was aborted by the network.
*/
#define ENETRESET 39
/**
* Network unreachable. No route to the network is present.
*/
#define ENETUNREACH 40
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
#define ENFILE 41
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
#define ENOBUFS 42
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
#define ENODATA 43
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
#define ENODEV 44
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
#define ENOENT 45
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
#define ENOEXEC 46
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
#define ENOLCK 47
/**
* Reserved.
*/
#define ENOLINK 48
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
#define ENOMEM 49
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
#define ENOMSG 50
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
#define ENOPROTOOPT 51
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
#define ENOSPC 52
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
#define ENOSR 53
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
#define ENOSTR 54
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
#define ENOSYS 55
/**
* Socket not connected. The socket is not connected.
*/
#define ENOTCONN 56
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- \<slash\> character and ends
* with one or more trailing \<slash\> characters.
*/
#define ENOTDIR 57
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
#define ENOTEMPTY 58
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
#define ENOTRECOVERABLE 59
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
#define ENOTSOCK 60
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
#define ENOTSUP 61
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
#define ENOTTY 62
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
#define ENXIO 63
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
#define EOPNOTSUPP 64
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
#define EOVERFLOW 65
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
#define EOWNERDEAD 66
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
#define EPERM 67
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
#define EPIPE 68
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
#define EPROTO 69
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
#define EPROTONOSUPPORT 70
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
#define EPROTOTYPE 71
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
#define ERANGE 72
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
#define EROFS 73
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
#define ESPIPE 74
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
#define ESRCH 75
/**
* Reserved.
*/
#define ESTALE 76
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
#define ETIME 77
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
#define ETIMEDOUT 78
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
#define ETXTBSY 79
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
#define EWOULDBLOCK 80
/**
* Improper link. A link to a file on another file system was attempted.
*/
#define EXDEV 81
#ifdef __kernel__
#define __ERRNO_MAX 82
#endif
#endif // !__FENNIX_API_ERRNO_H__

View File

@ -0,0 +1,109 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_FCNTL_H__
#define __FENNIX_API_FCNTL_H__
#ifdef __kernel__
#include <types.h>
#endif
/* cmd */
#define F_DUPFD 0x1
#define F_DUPFD_CLOEXEC 0x101
#define F_DUPFD_CLOFORK 0x201
#define F_GETFD 0x2
#define F_SETFD 0x3
#define F_GETFL 0x4
#define F_SETFL 0x5
#define F_GETLK 0x6
#define F_SETLK 0x7
#define F_SETLKW 0x8
#define F_OFD_GETLK 0x9
#define F_OFD_SETLK 0xA
#define F_OFD_SETLKW 0xB
#define F_GETOWN 0xC
#define F_GETOWN_EX 0xD
#define F_SETOWN 0xE
#define F_SETOWN_EX 0xF
#define FD_CLOEXEC 0x1
#define FD_CLOFORK 0x2
/* l_type */
#define F_RDLCK 0x1
#define F_UNLCK 0x2
#define F_WRLCK 0x3
/* type */
#define F_OWNER_PID 0
#define F_OWNER_PGRP 1
/* oflag */
#define O_CLOEXEC 02000000
#define O_CLOFORK 04000000
#define O_CREAT 0x8
#define O_DIRECTORY 0200000
#define O_EXCL 0x20
#define O_NOCTTY 0x40
#define O_NOFOLLOW 0400000
#define O_TRUNC 0x400
#define O_TTY_INIT 0x800
#define O_APPEND 0x4
#define O_DSYNC 0x10
#define O_NONBLOCK 0x80
#define O_RSYNC 0x100
#define O_SYNC 0x200
#define O_ACCMODE 0x3
#define O_EXEC 0x4
#define O_RDONLY 0x1
#define O_RDWR 0x3
#define O_SEARCH 0x10
#define O_WRONLY 0x2
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#endif // !__FENNIX_API_FCNTL_H__

View File

@ -0,0 +1,124 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_SIGNAL_H
#define _BITS_SIGNAL_H
#include <bits/syscalls.h>
#define SIGNULL __SYS_SIGNULL
#define SIGABRT __SYS_SIGABRT
#define SIGALRM __SYS_SIGALRM
#define SIGBUS __SYS_SIGBUS
#define SIGCHLD __SYS_SIGCHLD
#define SIGCONT __SYS_SIGCONT
#define SIGFPE __SYS_SIGFPE
#define SIGHUP __SYS_SIGHUP
#define SIGILL __SYS_SIGILL
#define SIGINT __SYS_SIGINT
#define SIGKILL __SYS_SIGKILL
#define SIGPIPE __SYS_SIGPIPE
#define SIGQUIT __SYS_SIGQUIT
#define SIGSEGV __SYS_SIGSEGV
#define SIGSTOP __SYS_SIGSTOP
#define SIGTERM __SYS_SIGTERM
#define SIGTSTP __SYS_SIGTSTP
#define SIGTTIN __SYS_SIGTTIN
#define SIGTTOU __SYS_SIGTTOU
#define SIGUSR1 __SYS_SIGUSR1
#define SIGUSR2 __SYS_SIGUSR2
#define SIGPOLL __SYS_SIGPOLL
#define SIGPROF __SYS_SIGPROF
#define SIGSYS __SYS_SIGSYS
#define SIGTRAP __SYS_SIGTRAP
#define SIGURG __SYS_SIGURG
#define SIGVTALRM __SYS_SIGVTALRM
#define SIGXCPU __SYS_SIGXCPU
#define SIGXFSZ __SYS_SIGXFSZ
#define SIGCOMP1 __SYS_SIGCOMP1
#define SIGCOMP2 __SYS_SIGCOMP2
#define SIGCOMP3 __SYS_SIGCOMP3
#define SIGRTMIN __SYS_SIGRTMIN
#define SIGRT_1 __SYS_SIGRT_1
#define SIGRT_2 __SYS_SIGRT_2
#define SIGRT_3 __SYS_SIGRT_3
#define SIGRT_4 __SYS_SIGRT_4
#define SIGRT_5 __SYS_SIGRT_5
#define SIGRT_6 __SYS_SIGRT_6
#define SIGRT_7 __SYS_SIGRT_7
#define SIGRT_8 __SYS_SIGRT_8
#define SIGRT_9 __SYS_SIGRT_9
#define SIGRT_10 __SYS_SIGRT_10
#define SIGRT_11 __SYS_SIGRT_11
#define SIGRT_12 __SYS_SIGRT_12
#define SIGRT_13 __SYS_SIGRT_13
#define SIGRT_14 __SYS_SIGRT_14
#define SIGRT_15 __SYS_SIGRT_15
#define SIGRT_16 __SYS_SIGRT_16
#define SIGRT_17 __SYS_SIGRT_17
#define SIGRT_18 __SYS_SIGRT_18
#define SIGRT_19 __SYS_SIGRT_19
#define SIGRT_20 __SYS_SIGRT_20
#define SIGRT_21 __SYS_SIGRT_21
#define SIGRT_22 __SYS_SIGRT_22
#define SIGRT_23 __SYS_SIGRT_23
#define SIGRT_24 __SYS_SIGRT_24
#define SIGRT_25 __SYS_SIGRT_25
#define SIGRT_26 __SYS_SIGRT_26
#define SIGRT_27 __SYS_SIGRT_27
#define SIGRT_28 __SYS_SIGRT_28
#define SIGRT_29 __SYS_SIGRT_29
#define SIGRT_30 __SYS_SIGRT_30
#define SIGRT_31 __SYS_SIGRT_31
#define SIGRTMAX __SYS_SIGRTMAX
#define SIGNAL_MAX __SYS_SIGNAL_MAX
#define SIG_TERM __SYS_SIG_TERM
// #define SIG_IGN __SYS_SIG_IGN
#define SIG_CORE __SYS_SIG_CORE
#define SIG_STOP __SYS_SIG_STOP
#define SIG_CONT __SYS_SIG_CONT
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
#define SA_ONSTACK __SYS_SA_ONSTACK
#define SA_RESETHAND __SYS_SA_RESETHAND
#define SA_RESTART __SYS_SA_RESTART
#define SA_SIGINFO __SYS_SA_SIGINFO
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
#define SA_NODEFER __SYS_SA_NODEFER
#define SS_ONSTACK
#define SS_DISABLE
#define MINSIGSTKSZ
#define SIGSTKSZ
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
typedef unsigned long sigset_t;
#endif // _BITS_SIGNAL_H

View File

@ -0,0 +1,34 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_SOCKET_H
#define _BITS_SOCKET_H
#define __socklen_t_defined
typedef __UINT32_TYPE__ socklen_t;
#define __sa_family_t_defined
typedef unsigned int sa_family_t;
#define __sockaddr_defined
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
#endif // _BITS_SOCKET_H

View File

@ -15,8 +15,18 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#if __has_include(<interface/fcntl.h>)
#include <interface/fcntl.h>
#else
#include <fcntl.h>
#endif
#ifndef __fennix__
#error "__fennix__ not defined"
#endif
#pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum
{
__SYS_O_RDONLY = 0x1,
__SYS_O_WRONLY = 0x2,
__SYS_O_RDWR = 0x3,
__SYS_O_APPEND = 0x4,
__SYS_O_CREAT = 0x8,
__SYS_O_DSYNC = 0x10,
__SYS_O_EXCL = 0x20,
__SYS_O_NOCTTY = 0x40,
__SYS_O_NONBLOCK = 0x80,
__SYS_O_RSYNC = 0x100,
__SYS_O_SYNC = 0x200,
__SYS_O_TRUNC = 0x400
__SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t;
typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/
#define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/**
* @brief List of syscalls
*
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid
*/
SYS_IOCTL,
/**
* @brief Function control
*
* @code
* int fcntl(int fd, int cmd, void *arg);
* @endcode
*
* @details Manipulates the underlying parameters of a device.
*
* @param fd File descriptor referring to the device
* @param cmd Device-specific request code
* @param arg Argument for the request
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not valid
* - #EINVAL if the request is invalid
*/
SYS_FCNTL,
/* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied
*/
SYS_RENAME,
/**
* @brief Get unix name information
*
* @code
* int uname(struct kutsname *buf);
* @endcode
*
* @details Retrieves information about the operating system.
*
* @param buf Pointer to `kutsname` structure to store information
*
* @return
* - #EOK on success
* - #EFAULT if `buf` is outside accessible address space
*/
SYS_UNAME,
/**
* @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
/** @copydoc SYS_FCNTL */
#define call_fcntl(fd, cmd, arg) syscall3(SYS_FCNTL, (scarg)fd, (scarg)cmd, (scarg)arg)
/* File Status */
/** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

View File

View File

@ -0,0 +1,159 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_ERRNO_H
#define _BITS_ERRNO_H
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define EDOM 33
#define ERANGE 34
#define EDEADLK 35
#define ENAMETOOLONG 36
#define ENOLCK 37
#define ENOSYS 38
#define ENOTEMPTY 39
#define ELOOP 40
#define EWOULDBLOCK 41
#define ENOMSG 42
#define EIDRM 43
#define ECHRNG 44
#define EL2NSYNC 45
#define EL3HLT 46
#define EL3RST 47
#define ELNRNG 48
#define EUNATCH 49
#define ENOCSI 50
#define EL2HLT 51
#define EBADE 52
#define EBADR 53
#define EXFULL 54
#define ENOANO 55
#define EBADRQC 56
#define EBADSLT 57
#define EDEADLOCK 58
#define EBFONT 59
#define ENOSTR 60
#define ENODATA 61
#define ETIME 62
#define ENOSR 63
#define ENONET 64
#define ENOPKG 65
#define EREMOTE 66
#define ENOLINK 67
#define EADV 68
#define ESRMNT 69
#define ECOMM 70
#define EPROTO 71
#define EMULTIHOP 72
#define EDOTDOT 73
#define EBADMSG 74
#define EOVERFLOW 75
#define ENOTUNIQ 76
#define EBADFD 77
#define EREMCHG 78
#define ELIBACC 79
#define ELIBBAD 80
#define ELIBSCN 81
#define ELIBMAX 82
#define ELIBEXEC 83
#define EILSEQ 84
#define ERESTART 85
#define ESTRPIPE 86
#define EUSERS 87
#define ENOTSOCK 88
#define EDESTADDRREQ 89
#define EMSGSIZE 90
#define EPROTOTYPE 91
#define ENOPROTOOPT 92
#define EPROTONOSUPPORT 93
#define ESOCKTNOSUPPORT 94
#define EOPNOTSUPP 95
#define EPFNOSUPPORT 96
#define EAFNOSUPPORT 97
#define EADDRINUSE 98
#define EADDRNOTAVAIL 99
#define ENETDOWN 100
#define ENETUNREACH 101
#define ENETRESET 102
#define ECONNABORTED 103
#define ECONNRESET 104
#define ENOBUFS 105
#define EISCONN 106
#define ENOTCONN 107
#define ESHUTDOWN 108
#define ETOOMANYREFS 109
#define ETIMEDOUT 110
#define ECONNREFUSED 111
#define EHOSTDOWN 112
#define EHOSTUNREACH 113
#define EALREADY 114
#define EINPROGRESS 115
#define ESTALE 116
#define EUCLEAN 117
#define ENOTNAM 118
#define ENAVAIL 119
#define EISNAM 120
#define EREMOTEIO 121
#define EDQUOT 122
#define ENOMEDIUM 123
#define EMEDIUMTYPE 124
#define ECANCELED 125
#define ENOKEY 126
#define EKEYEXPIRED 127
#define EKEYREVOKED 128
#define EKEYREJECTED 129
#define EOWNERDEAD 130
#define ENOTRECOVERABLE 131
#define ERFKILL 132
#define EHWPOISON 133
#define ENOTSUP EOPNOTSUPP
#endif // _BITS_ERRNO_H

View File

@ -0,0 +1,74 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_SIGNAL_H
#define _BITS_SIGNAL_H
typedef unsigned long sigset_t;
#define NSIG 32
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
#define SIGLOST 29
#define SIGPWR 30
#define SIGSYS 31
#define SIGUNUSED 31
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
typedef void __signalfn_t(int);
typedef __signalfn_t *__sighandler_t;
#define SIG_DFL ((__sighandler_t)0)
#define SIG_IGN ((__sighandler_t)1)
#define SIG_ERR ((__sighandler_t) - 1)
#endif // _BITS_SIGNAL_H

View File

@ -0,0 +1,34 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_SOCKET_H
#define _BITS_SOCKET_H
#define __socklen_t_defined
typedef __UINT32_TYPE__ socklen_t;
#define __sa_family_t_defined
typedef unsigned int sa_family_t;
#define __sockaddr_defined
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
#endif // _BITS_SOCKET_H

View File

@ -0,0 +1,474 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BITS_SYSCALLS_H
#define _BITS_SYSCALLS_H
#pragma region Syscall Wrappers
#define scarg __UINTPTR_TYPE__
static inline scarg syscall0(scarg syscall)
{
scarg ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall1(scarg syscall, scarg arg1)
{
scarg ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{
scarg ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{
scarg ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{
scarg ret;
register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{
scarg ret;
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{
scarg ret;
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#pragma endregion Syscall Wrappers
#define sys_read 0
#define sys_write 1
#define sys_open 2
#define sys_close 3
#define sys_stat 4
#define sys_fstat 5
#define sys_lstat 6
#define sys_poll 7
#define sys_lseek 8
#define sys_mmap 9
#define sys_mprotect 10
#define sys_munmap 11
#define sys_brk 12
#define sys_rt_sigaction 13
#define sys_rt_sigprocmask 14
#define sys_rt_sigreturn 15
#define sys_ioctl 16
#define sys_pread64 17
#define sys_pwrite64 18
#define sys_readv 19
#define sys_writev 20
#define sys_access 21
#define sys_pipe 22
#define sys_select 23
#define sys_sched_yield 24
#define sys_mremap 25
#define sys_msync 26
#define sys_mincore 27
#define sys_madvise 28
#define sys_shmget 29
#define sys_shmat 30
#define sys_shmctl 31
#define sys_dup 32
#define sys_dup2 33
#define sys_pause 34
#define sys_nanosleep 35
#define sys_getitimer 36
#define sys_alarm 37
#define sys_setitimer 38
#define sys_getpid 39
#define sys_sendfile 40
#define sys_socket 41
#define sys_connect 42
#define sys_accept 43
#define sys_sendto 44
#define sys_recvfrom 45
#define sys_sendmsg 46
#define sys_recvmsg 47
#define sys_shutdown 48
#define sys_bind 49
#define sys_listen 50
#define sys_getsockname 51
#define sys_getpeername 52
#define sys_socketpair 53
#define sys_setsockopt 54
#define sys_getsockopt 55
#define sys_clone 56
#define sys_fork 57
#define sys_vfork 58
#define sys_execve 59
#define sys_exit 60
#define sys_wait4 61
#define sys_kill 62
#define sys_uname 63
#define sys_semget 64
#define sys_semop 65
#define sys_semctl 66
#define sys_shmdt 67
#define sys_msgget 68
#define sys_msgsnd 69
#define sys_msgrcv 70
#define sys_msgctl 71
#define sys_fcntl 72
#define sys_flock 73
#define sys_fsync 74
#define sys_fdatasync 75
#define sys_truncate 76
#define sys_ftruncate 77
#define sys_getdents 78
#define sys_getcwd 79
#define sys_chdir 80
#define sys_fchdir 81
#define sys_rename 82
#define sys_mkdir 83
#define sys_rmdir 84
#define sys_creat 85
#define sys_link 86
#define sys_unlink 87
#define sys_symlink 88
#define sys_readlink 89
#define sys_chmod 90
#define sys_fchmod 91
#define sys_chown 92
#define sys_fchown 93
#define sys_lchown 94
#define sys_umask 95
#define sys_gettimeofday 96
#define sys_getrlimit 97
#define sys_getrusage 98
#define sys_sysinfo 99
#define sys_times 100
#define sys_ptrace 101
#define sys_getuid 102
#define sys_syslog 103
#define sys_getgid 104
#define sys_setuid 105
#define sys_setgid 106
#define sys_geteuid 107
#define sys_getegid 108
#define sys_setpgid 109
#define sys_getppid 110
#define sys_getpgrp 111
#define sys_setsid 112
#define sys_setreuid 113
#define sys_setregid 114
#define sys_getgroups 115
#define sys_setgroups 116
#define sys_setresuid 117
#define sys_getresuid 118
#define sys_setresgid 119
#define sys_getresgid 120
#define sys_getpgid 121
#define sys_setfsuid 122
#define sys_setfsgid 123
#define sys_getsid 124
#define sys_capget 125
#define sys_capset 126
#define sys_rt_sigpending 127
#define sys_rt_sigtimedwait 128
#define sys_rt_sigqueueinfo 129
#define sys_rt_sigsuspend 130
#define sys_sigaltstack 131
#define sys_utime 132
#define sys_mknod 133
#define sys_uselib 134
#define sys_personality 135
#define sys_ustat 136
#define sys_statfs 137
#define sys_fstatfs 138
#define sys_sysfs 139
#define sys_getpriority 140
#define sys_setpriority 141
#define sys_sched_setparam 142
#define sys_sched_getparam 143
#define sys_sched_setscheduler 144
#define sys_sched_getscheduler 145
#define sys_sched_get_priority_max 146
#define sys_sched_get_priority_min 147
#define sys_sched_rr_get_interval 148
#define sys_mlock 149
#define sys_munlock 150
#define sys_mlockall 151
#define sys_munlockall 152
#define sys_vhangup 153
#define sys_modify_ldt 154
#define sys_pivot_root 155
#define sys__sysctl 156
#define sys_prctl 157
#define sys_arch_prctl 158
#define sys_adjtimex 159
#define sys_setrlimit 160
#define sys_chroot 161
#define sys_sync 162
#define sys_acct 163
#define sys_settimeofday 164
#define sys_mount 165
#define sys_umount2 166
#define sys_swapon 167
#define sys_swapoff 168
#define sys_reboot 169
#define sys_sethostname 170
#define sys_setdomainname 171
#define sys_iopl 172
#define sys_ioperm 173
#define sys_create_module 174
#define sys_init_module 175
#define sys_delete_module 176
#define sys_get_kernel_syms 177
#define sys_query_module 178
#define sys_quotactl 179
#define sys_nfsservctl 180
#define sys_getpmsg 181
#define sys_putpmsg 182
#define sys_afs_syscall 183
#define sys_tuxcall 184
#define sys_security 185
#define sys_gettid 186
#define sys_readahead 187
#define sys_setxattr 188
#define sys_lsetxattr 189
#define sys_fsetxattr 190
#define sys_getxattr 191
#define sys_lgetxattr 192
#define sys_fgetxattr 193
#define sys_listxattr 194
#define sys_llistxattr 195
#define sys_flistxattr 196
#define sys_removexattr 197
#define sys_lremovexattr 198
#define sys_fremovexattr 199
#define sys_tkill 200
#define sys_time 201
#define sys_futex 202
#define sys_sched_setaffinity 203
#define sys_sched_getaffinity 204
#define sys_set_thread_area 205
#define sys_io_setup 206
#define sys_io_destroy 207
#define sys_io_getevents 208
#define sys_io_submit 209
#define sys_io_cancel 210
#define sys_get_thread_area 211
#define sys_lookup_dcookie 212
#define sys_epoll_create 213
#define sys_epoll_ctl_old 214
#define sys_epoll_wait_old 215
#define sys_remap_file_pages 216
#define sys_getdents64 217
#define sys_set_tid_address 218
#define sys_restart_syscall 219
#define sys_semtimedop 220
#define sys_fadvise64 221
#define sys_timer_create 222
#define sys_timer_settime 223
#define sys_timer_gettime 224
#define sys_timer_getoverrun 225
#define sys_timer_delete 226
#define sys_clock_settime 227
#define sys_clock_gettime 228
#define sys_clock_getres 229
#define sys_clock_nanosleep 230
#define sys_exit_group 231
#define sys_epoll_wait 232
#define sys_epoll_ctl 233
#define sys_tgkill 234
#define sys_utimes 235
#define sys_vserver 236
#define sys_mbind 237
#define sys_set_mempolicy 238
#define sys_get_mempolicy 239
#define sys_mq_open 240
#define sys_mq_unlink 241
#define sys_mq_timedsend 242
#define sys_mq_timedreceive 243
#define sys_mq_notify 244
#define sys_mq_getsetattr 245
#define sys_kexec_load 246
#define sys_waitid 247
#define sys_add_key 248
#define sys_request_key 249
#define sys_keyctl 250
#define sys_ioprio_set 251
#define sys_ioprio_get 252
#define sys_inotify_init 253
#define sys_inotify_add_watch 254
#define sys_inotify_rm_watch 255
#define sys_migrate_pages 256
#define sys_openat 257
#define sys_mkdirat 258
#define sys_mknodat 259
#define sys_fchownat 260
#define sys_futimesat 261
#define sys_newfstatat 262
#define sys_unlinkat 263
#define sys_renameat 264
#define sys_linkat 265
#define sys_symlinkat 266
#define sys_readlinkat 267
#define sys_fchmodat 268
#define sys_faccessat 269
#define sys_pselect6 270
#define sys_ppoll 271
#define sys_unshare 272
#define sys_set_robust_list 273
#define sys_get_robust_list 274
#define sys_splice 275
#define sys_tee 276
#define sys_sync_file_range 277
#define sys_vmsplice 278
#define sys_move_pages 279
#define sys_utimensat 280
#define sys_epoll_pwait 281
#define sys_signalfd 282
#define sys_timerfd_create 283
#define sys_eventfd 284
#define sys_fallocate 285
#define sys_timerfd_settime 286
#define sys_timerfd_gettime 287
#define sys_accept4 288
#define sys_signalfd4 289
#define sys_eventfd2 290
#define sys_epoll_create1 291
#define sys_dup3 292
#define sys_pipe2 293
#define sys_inotify_init1 294
#define sys_preadv 295
#define sys_pwritev 296
#define sys_rt_tgsigqueueinfo 297
#define sys_perf_event_open 298
#define sys_recvmmsg 299
#define sys_fanotify_init 300
#define sys_fanotify_mark 301
#define sys_prlimit64 302
#define sys_name_to_handle_at 303
#define sys_open_by_handle_at 304
#define sys_clock_adjtime 305
#define sys_syncfs 306
#define sys_sendmmsg 307
#define sys_setns 308
#define sys_getcpu 309
#define sys_process_vm_readv 310
#define sys_process_vm_writev 311
#define sys_kcmp 312
#define sys_finit_module 313
#define sys_sched_setattr 314
#define sys_sched_getattr 315
#define sys_renameat2 316
#define sys_seccomp 317
#define sys_getrandom 318
#define sys_memfd_create 319
#define sys_kexec_file_load 320
#define sys_bpf 321
#define sys_execveat 322
#define sys_userfaultfd 323
#define sys_membarrier 324
#define sys_mlock2 325
#define sys_copy_file_range 326
#define sys_preadv2 327
#define sys_pwritev2 328
#define sys_pkey_mprotect 329
#define sys_pkey_alloc 330
#define sys_pkey_free 331
#define sys_statx 332
#define sys_io_pgetevents 333
#define sys_rseq 334
#define sys_pidfd_send_signal 424
#define sys_io_uring_setup 425
#define sys_io_uring_enter 426
#define sys_io_uring_register 427
#define sys_open_tree 428
#define sys_move_mount 429
#define sys_fsopen 430
#define sys_fsconfig 431
#define sys_fsmount 432
#define sys_fspick 433
#define sys_pidfd_open 434
#define sys_clone3 435
#define sys_close_range 436
#define sys_openat2 437
#define sys_pidfd_getfd 438
#define sys_faccessat2 439
#define sys_process_madvise 440
#define sys_epoll_pwait2 441
#define sys_mount_setattr 442
#define sys_quotactl_fd 443
#define sys_landlock_create_ruleset 444
#define sys_landlock_add_rule 445
#define sys_landlock_restrict_self 446
#define sys_memfd_secret 447
#define sys_process_mrelease 448
struct kutsname
{
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
};
#endif // _BITS_SYSCALLS_H

View File

@ -0,0 +1,74 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef FENNIX_BITS_LIBC_H
#define FENNIX_BITS_LIBC_H
#include <bits/socket.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __kernel__
#error "Kernel code should not include this header"
#endif // __kernel__
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
#define sysdep(name) \
__libc_##name
void sysdep(Exit)(int Status);
int sysdep(Accept)(int Socket, struct sockaddr *restrict Address, socklen_t *restrict AddressLength);
int sysdep(Bind)(int Socket, const struct sockaddr *Address, socklen_t AddressLength);
int sysdep(Connect)(int Socket, const struct sockaddr *Address, socklen_t AddressLength);
int sysdep(Listen)(int Socket, int Backlog);
int sysdep(Socket)(int Domain, int Type, int Protocol);
int sysdep(UnixName)(struct utsname *Name);
int sysdep(WaitProcessID)(pid_t ProcessID, int *Status, int Options);
int sysdep(IOControl)(int Descriptor, unsigned long Operation, void *Argument);
void *sysdep(MemoryMap)(void *Address, size_t Length, int Protection, int Flags, int Descriptor, off_t Offset);
int sysdep(MemoryUnmap)(void *Address, size_t Length);
int sysdep(MemoryProtect)(void *Address, size_t Length, int Protection);
int sysdep(Fork)(void);
int sysdep(Read)(int Descriptor, void *Buffer, size_t Size);
int sysdep(Write)(int Descriptor, const void *Buffer, size_t Size);
int sysdep(PRead)(int Descriptor, void *Buffer, size_t Size, off_t Offset);
int sysdep(PWrite)(int Descriptor, const void *Buffer, size_t Size, off_t Offset);
int sysdep(Open)(const char *Pathname, int Flags, mode_t Mode);
int sysdep(Close)(int Descriptor);
int sysdep(Access)(const char *Pathname, int Mode);
int sysdep(Tell)(int Descriptor);
int sysdep(Seek)(int Descriptor, off_t Offset, int Whence);
pid_t sysdep(GetProcessID)(void);
pid_t sysdep(GetParentProcessID)(void);
int sysdep(Execve)(const char *Pathname, char *const *Argv, char *const *Envp);
int sysdep(Kill)(pid_t ProcessID, int Signal);
int sysdep(Stat)(const char *Pathname, struct stat *Statbuf);
int sysdep(FStat)(int Descriptor, struct stat *Statbuf);
int sysdep(LStat)(const char *Pathname, struct stat *Statbuf);
int sysdep(Truncate)(const char *Pathname, off_t Length);
int sysdep(MakeDirectory)(const char *Pathname, mode_t Mode);
int sysdep(ProcessControl)(unsigned long Option, unsigned long Arg1, unsigned long Arg2, unsigned long Arg3, unsigned long Arg4);
int sysdep(ChangeDirectory)(const char *Pathname);
char *sysdep(GetWorkingDirectory)(char *Buffer, size_t Size);
int sysdep(Brk)(void *Address);
int sysdep(FileControl)(int Descriptor, int Command, void *Arg);
#endif // FENNIX_BITS_LIBC_H

View File

@ -0,0 +1,36 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __BITS_TYPES_SIGNAL_H
#define __BITS_TYPES_SIGNAL_H
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
typedef struct sigevent
{
int sigev_notify; /* Notification type. */
int sigev_signo; /* Signal number. */
union sigval sigev_value; /* Signal value. */
void (*sigev_notify_function)(union sigval); /* Notification function. */
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
} sigevent;
#endif // __BITS_TYPES_SIGNAL_H

View File

@ -1,592 +1,24 @@
/*
This file is part of Fennix Kernel.
This file is part of Fennix C Library.
Fennix Kernel is free software: you can redistribute it and/or
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_ERRNO_H__
#define __FENNIX_API_ERRNO_H__
#ifndef _ERRNO_H
#define _ERRNO_H
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- \<slash\> character and ends
* with one or more trailing \<slash\> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <bits/errno.h>
#ifdef __cplusplus
extern "C"
@ -602,4 +34,4 @@ extern "C"
#define errno (*__errno_location())
#endif // !__FENNIX_API_ERRNO_H__
#endif // _ERRNO_H

View File

@ -24,77 +24,7 @@ extern "C"
#endif // __cplusplus
#include <sys/types.h>
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#define F_DUPFD
#define F_DUPFD_CLOEXEC
#define F_DUPFD_CLOFORK
#define F_GETFD
#define F_SETFD
#define F_GETFL
#define F_SETFL
#define F_GETLK
#define F_SETLK
#define F_SETLKW
#define F_OFD_GETLK
#define F_OFD_SETLK
#define F_OFD_SETLKW
#define F_GETOWN
#define F_GETOWN_EX
#define F_SETOWN
#define F_SETOWN_EX
#define FD_CLOEXEC
#define FD_CLOFORK
#define F_RDLCK
#define F_UNLCK
#define F_WRLCK
#define F_OWNER_PID
#define F_OWNER_PGRP
#define O_CLOEXEC 02000000
#define O_CLOFORK
#define O_CREAT 0100
#define O_DIRECTORY
#define O_EXCL 0200
#define O_NOCTTY
#define O_NOFOLLOW 0400000
#define O_TRUNC 01000
#define O_TTY_INIT
#define O_APPEND 02000
#define O_DSYNC
#define O_NONBLOCK
#define O_RSYNC
#define O_SYNC
#define O_ACCMODE
#define O_EXEC
#define O_RDONLY 00
#define O_RDWR 02
#define O_SEARCH
#define O_WRONLY 01
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
#include <bits/fcntl.h>
int creat(const char *path, mode_t mode);
int fcntl(int fildes, int cmd, ...);

View File

@ -0,0 +1,28 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _GETOPT_H
#define _GETOPT_H
#include <unistd.h>
extern int opterr, optind, optopt;
extern char *optarg;
int getopt(int argc, char *const argv[], const char *optstring);
#endif // _GETOPT_H

View File

@ -287,6 +287,10 @@ typedef long double double_t;
double y1(double x);
double yn(int n, double x);
void sincos(double x, double *s, double *c);
void sincosf(float x, float *s, float *c);
void sincosl(long double x, long double *s, long double *c);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@ -0,0 +1,68 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _REGEX_H
#define _REGEX_H
#include <sys/types.h>
#include <stddef.h>
typedef struct
{
size_t re_nsub; /* Number of parenthesized subexpressions */
} regex_t;
typedef ptrdiff_t regoff_t;
typedef struct
{
regoff_t rm_so; /* Byte offset to start of substring */
regoff_t rm_eo; /* Byte offset after end of substring */
} regmatch_t;
/* Flags for regcomp() */
#define REG_EXTENDED 0x01 /* Use Extended Regular Expressions */
#define REG_ICASE 0x02 /* Case-insensitive matching */
#define REG_MINIMAL 0x04 /* Leftmost shortest match (for REG_EXTENDED) */
#define REG_NOSUB 0x08 /* Suppress subexpression reporting */
#define REG_NEWLINE 0x10 /* Alter newline handling */
/* Flags for regexec() */
#define REG_NOTBOL 0x01 /* ^ does not match start of string */
#define REG_NOTEOL 0x02 /* $ does not match end of string */
/* Error codes */
#define REG_NOMATCH 1 /* No match found */
#define REG_BADPAT 2 /* Invalid regular expression */
#define REG_ECOLLATE 3 /* Invalid collating element */
#define REG_ECTYPE 4 /* Invalid character class */
#define REG_EESCAPE 5 /* Trailing backslash */
#define REG_ESUBREG 6 /* Invalid backreference */
#define REG_EBRACK 7 /* Unbalanced '[]' */
#define REG_EPAREN 8 /* Unbalanced '()' */
#define REG_EBRACE 9 /* Unbalanced '{}' */
#define REG_BADBR 10 /* Invalid content in {} */
#define REG_ERANGE 11 /* Invalid range endpoint */
#define REG_ESPACE 12 /* Memory exhaustion */
#define REG_BADRPT 13 /* Invalid repetition operator */
int regcomp(regex_t *restrict preg, const char *restrict pattern, int cflags);
size_t regerror(int errcode, const regex_t *restrict preg, char *restrict errbuf, size_t errbuf_size);
int regexec(const regex_t *restrict preg, const char *restrict string, size_t nmatch, regmatch_t pmatch[restrict], int eflags);
void regfree(regex_t *preg);
#endif /* _REGEX_H */

View File

@ -24,115 +24,11 @@ extern "C"
#endif // __cplusplus
#include <sys/types.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <bits/types/timespec.h>
#define SIGNULL __SYS_SIGNULL
#define SIGABRT __SYS_SIGABRT
#define SIGALRM __SYS_SIGALRM
#define SIGBUS __SYS_SIGBUS
#define SIGCHLD __SYS_SIGCHLD
#define SIGCONT __SYS_SIGCONT
#define SIGFPE __SYS_SIGFPE
#define SIGHUP __SYS_SIGHUP
#define SIGILL __SYS_SIGILL
#define SIGINT __SYS_SIGINT
#define SIGKILL __SYS_SIGKILL
#define SIGPIPE __SYS_SIGPIPE
#define SIGQUIT __SYS_SIGQUIT
#define SIGSEGV __SYS_SIGSEGV
#define SIGSTOP __SYS_SIGSTOP
#define SIGTERM __SYS_SIGTERM
#define SIGTSTP __SYS_SIGTSTP
#define SIGTTIN __SYS_SIGTTIN
#define SIGTTOU __SYS_SIGTTOU
#define SIGUSR1 __SYS_SIGUSR1
#define SIGUSR2 __SYS_SIGUSR2
#define SIGPOLL __SYS_SIGPOLL
#define SIGPROF __SYS_SIGPROF
#define SIGSYS __SYS_SIGSYS
#define SIGTRAP __SYS_SIGTRAP
#define SIGURG __SYS_SIGURG
#define SIGVTALRM __SYS_SIGVTALRM
#define SIGXCPU __SYS_SIGXCPU
#define SIGXFSZ __SYS_SIGXFSZ
#define SIGCOMP1 __SYS_SIGCOMP1
#define SIGCOMP2 __SYS_SIGCOMP2
#define SIGCOMP3 __SYS_SIGCOMP3
#define SIGRTMIN __SYS_SIGRTMIN
#define SIGRT_1 __SYS_SIGRT_1
#define SIGRT_2 __SYS_SIGRT_2
#define SIGRT_3 __SYS_SIGRT_3
#define SIGRT_4 __SYS_SIGRT_4
#define SIGRT_5 __SYS_SIGRT_5
#define SIGRT_6 __SYS_SIGRT_6
#define SIGRT_7 __SYS_SIGRT_7
#define SIGRT_8 __SYS_SIGRT_8
#define SIGRT_9 __SYS_SIGRT_9
#define SIGRT_10 __SYS_SIGRT_10
#define SIGRT_11 __SYS_SIGRT_11
#define SIGRT_12 __SYS_SIGRT_12
#define SIGRT_13 __SYS_SIGRT_13
#define SIGRT_14 __SYS_SIGRT_14
#define SIGRT_15 __SYS_SIGRT_15
#define SIGRT_16 __SYS_SIGRT_16
#define SIGRT_17 __SYS_SIGRT_17
#define SIGRT_18 __SYS_SIGRT_18
#define SIGRT_19 __SYS_SIGRT_19
#define SIGRT_20 __SYS_SIGRT_20
#define SIGRT_21 __SYS_SIGRT_21
#define SIGRT_22 __SYS_SIGRT_22
#define SIGRT_23 __SYS_SIGRT_23
#define SIGRT_24 __SYS_SIGRT_24
#define SIGRT_25 __SYS_SIGRT_25
#define SIGRT_26 __SYS_SIGRT_26
#define SIGRT_27 __SYS_SIGRT_27
#define SIGRT_28 __SYS_SIGRT_28
#define SIGRT_29 __SYS_SIGRT_29
#define SIGRT_30 __SYS_SIGRT_30
#define SIGRT_31 __SYS_SIGRT_31
#define SIGRTMAX __SYS_SIGRTMAX
#define SIGNAL_MAX __SYS_SIGNAL_MAX
#define SIG_TERM __SYS_SIG_TERM
// #define SIG_IGN __SYS_SIG_IGN
#define SIG_CORE __SYS_SIG_CORE
#define SIG_STOP __SYS_SIG_STOP
#define SIG_CONT __SYS_SIG_CONT
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
#define SA_ONSTACK __SYS_SA_ONSTACK
#define SA_RESETHAND __SYS_SA_RESETHAND
#define SA_RESTART __SYS_SA_RESTART
#define SA_SIGINFO __SYS_SA_SIGINFO
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
#define SA_NODEFER __SYS_SA_NODEFER
#define SS_ONSTACK
#define SS_DISABLE
#define MINSIGSTKSZ
#define SIGSTKSZ
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
typedef unsigned long sigset_t;
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
#include <bits/signal.h>
#include <bits/types/signal.h>
typedef struct siginfo_t
{
@ -149,15 +45,6 @@ extern "C"
union sigval si_value; /* Signal value. */
} siginfo_t;
typedef struct sigevent
{
int sigev_notify; /* Notification type. */
int sigev_signo; /* Signal number. */
union sigval sigev_value; /* Signal value. */
void (*sigev_notify_function)(union sigval); /* Notification function. */
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
} sigevent;
struct sigaction
{
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */

View File

@ -18,7 +18,65 @@
#ifndef _SYS_IOCTL_H
#define _SYS_IOCTL_H
#include <sys/types.h>
#include <termios.h>
#define __SID ('S' << 8)
#define I_NREAD (__SID | 1)
#define I_PUSH (__SID | 2)
#define I_POP (__SID | 3)
#define I_LOOK (__SID | 4)
#define I_FLUSH (__SID | 5)
#define I_SRDOPT (__SID | 6)
#define I_GRDOPT (__SID | 7)
#define I_STR (__SID | 8)
#define I_SETSIG (__SID | 9)
#define I_GETSIG (__SID | 10)
#define I_FIND (__SID | 11)
#define I_LINK (__SID | 12)
#define I_UNLINK (__SID | 13)
#define I_PEEK (__SID | 15)
#define I_FDINSERT (__SID | 16)
#define I_SENDFD (__SID | 17)
#define I_RECVFD (__SID | 14)
#define I_SWROPT (__SID | 19)
#define I_GWROPT (__SID | 20)
#define I_LIST (__SID | 21)
#define I_PLINK (__SID | 22)
#define I_PUNLINK (__SID | 23)
#define I_FLUSHBAND (__SID | 28)
#define I_CKBAND (__SID | 29)
#define I_GETBAND (__SID | 30)
#define I_ATMARK (__SID | 31)
#define I_SETCLTIME (__SID | 32)
#define I_GETCLTIME (__SID | 33)
#define I_CANPUT (__SID | 34)
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
#define TCGETA 0x5405
#define TCSETA 0x5406
#define TCSETAW 0x5407
#define TCSETAF 0x5408
#define TCSBRK 0x5409
#define TCXONC 0x540A
#define TCFLSH 0x540B
#define TIOCEXCL 0x540C
#define TIOCNXCL 0x540D
#define TIOCSCTTY 0x540E
#define TIOCGPGRP 0x540F
#define TIOCSPGRP 0x5410
#define TIOCOUTQ 0x5411
#define TIOCSTI 0x5412
#define TIOCGWINSZ 0x5413
#define TIOCSWINSZ 0x5414
#define TIOCMGET 0x5415
#define TIOCMBIS 0x5416
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCGSID 0x5429
int ioctl(int fd, unsigned long op, ...);

View File

@ -21,15 +21,26 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <bits/socket.h>
typedef uint32_t socklen_t;
#ifndef __socklen_t_defined
#define __socklen_t_defined
typedef __UINT32_TYPE__ socklen_t;
#endif
#ifndef __sa_family_t_defined
#define __sa_family_t_defined
typedef unsigned int sa_family_t;
#endif
#ifndef __sockaddr_defined
#define __sockaddr_defined
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
#endif
#define _SS_MAXSIZE 128
#define _SS_ALIGNSIZE (sizeof(int64_t))

View File

@ -42,14 +42,14 @@ extern "C"
blkcnt_t st_blocks; /* Number of blocks allocated for this object. */
};
#define S_IFMT
#define S_IFBLK
#define S_IFCHR
#define S_IFIFO
#define S_IFREG
#define S_IFDIR
#define S_IFLNK
#define S_IFSOCK
#define S_IFMT 0170000
#define S_IFBLK 0060000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_IFREG 0100000
#define S_IFDIR 0040000
#define S_IFLNK 0120000
#define S_IFSOCK 0140000
#define S_IRWXU 0700
#define S_IRUSR 0400
@ -68,21 +68,21 @@ extern "C"
#define S_ISGID 02000
#define S_ISVTX 01000
#define S_ISBLK(m)
#define S_ISCHR(m)
#define S_ISDIR(m)
#define S_ISFIFO(m)
#define S_ISREG(m)
#define S_ISLNK(m)
#define S_ISSOCK(m)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_TYPEISMQ(buf)
#define S_TYPEISSEM(buf)
#define S_TYPEISSHM(buf)
#define S_TYPEISTMO(buf)
#define S_TYPEISMQ(buf) 0
#define S_TYPEISSEM(buf) 0
#define S_TYPEISSHM(buf) 0
#define S_TYPEISTMO(buf) 0
#define UTIME_NOW
#define UTIME_OMIT
#define UTIME_NOW 0x3fffffff
#define UTIME_OMIT 0x3ffffffe
int chmod(const char *, mode_t);
int fchmod(int, mode_t);

View File

@ -30,10 +30,6 @@ extern "C"
#define restrict __restrict__
#endif // restrict
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
typedef long blkcnt_t;
typedef long blksize_t;

View File

@ -18,7 +18,7 @@
#ifndef _TERMIOS_H
#define _TERMIOS_H
#include <sys/ioctl.h>
#include <sys/types.h>
typedef unsigned char cc_t;
typedef unsigned int speed_t;

View File

@ -25,7 +25,7 @@ extern "C"
#include <bits/types/timespec.h>
#include <sys/types.h>
#include <signal.h>
#include <bits/types/signal.h>
#include <locale.h>
typedef struct tm

View File

@ -59,10 +59,10 @@ extern "C"
extern int optind, opterr, optopt;
extern char **environ;
int access(const char *, int);
int access(const char *path, int amode);
unsigned int alarm(unsigned int seconds);
int brk(void *);
int chdir(const char *);
int brk(void *addr);
int chdir(const char *path);
int chroot(const char *);
int chown(const char *, uid_t, gid_t);
int close(int fildes);
@ -87,7 +87,7 @@ extern "C"
long int fpathconf(int, int);
int fsync(int);
int ftruncate(int, off_t);
char *getcwd(char *, size_t);
char *getcwd(char *buf, size_t size);
int getdtablesize(void);
gid_t getegid(void);
uid_t geteuid(void);
@ -122,7 +122,7 @@ extern "C"
ssize_t read(int fildes, void *buf, size_t nbyte);
int readlink(const char *, char *, size_t);
int rmdir(const char *);
void *sbrk(intptr_t);
void *sbrk(intptr_t incr);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
pid_t setpgrp(void);

View File

@ -0,0 +1,21 @@
file(GLOB_RECURSE SYSDEPS_SOURCES ${SYSDEPS_PATH}/*.c ${SYSDEPS_GENERIC}/*.c)
file(GLOB_RECURSE INTERPRETER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
list(APPEND INTERPRETER_FILES ${SYSDEPS_SOURCES})
add_executable(ld.so ${INTERPRETER_FILES})
execute_process(COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(GIT_COMMIT)
add_compile_definitions(LIBC_GIT_COMMIT="${GIT_COMMIT}")
endif()
add_compile_definitions(FENNIX_DYNAMIC_LOADER="1")
install(TARGETS ld.so DESTINATION lib)
target_compile_options(ld.so PRIVATE -fvisibility=hidden -fPIC)
target_link_options(ld.so PRIVATE -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-e,_dl_start)

View File

@ -1,40 +0,0 @@
default:
$(error Do not run this Makefile directly!)
OBJECT_NAME := ld.so
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(OBJECT_NAME)
$(OBJECT_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OBJECT_NAME)
cp $(OBJECT_NAME) $(OUTPUT_DIR)$(OBJECT_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(OBJECT_NAME)

View File

@ -15,8 +15,9 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
@ -39,7 +40,7 @@ MemoryBlock *memory_pool = NULL;
void *request_page(size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void *addr = (void *)call_mmap(NULL, aligned_size, __SYS_PROT_READ | __SYS_PROT_WRITE, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE, -1, 0);
void *addr = (void *)sysdep(MemoryMap)(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if ((intptr_t)addr < 0)
return NULL;
return addr;
@ -48,7 +49,7 @@ void *request_page(size_t size)
void free_page(void *addr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
call_munmap(addr, aligned_size);
sysdep(MemoryUnmap)(addr, aligned_size);
}
MemoryBlock *allocate_block(size_t slot_size)

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>

View File

@ -15,11 +15,14 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <stddef.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "elf.h"
@ -167,9 +170,15 @@ __attribute__((noinline)) void *_dl_fixup(ElfInfo *Info, long RelIndex)
return ret;
}
#ifdef __fennix__
#include <fennix/syscalls.h>
#endif
int _dl_preload()
{
#ifdef __fennix__
call_api_version(0);
#endif
/* TODO: Do aditional checks for miscellaneous things */
@ -353,16 +362,16 @@ void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
strcpy(fullLibPath, "/lib/");
strcat(fullLibPath, libPath);
/* TODO: more checks and also check environment variables */
if (call_access(fullLibPath, __SYS_F_OK) != 0)
if (sysdep(Access)(fullLibPath, F_OK) != 0)
{
printf("dl: Can't access %s\n", fullLibPath);
return;
}
int fd = call_open(fullLibPath, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(fullLibPath, O_RDONLY, 0644);
int status = LoadElf(fd, fullLibPath, &info);
elem->d_un.d_ptr = (uintptr_t)info; /* if LoadElf fails, info will still be NULL */
call_close(fd);
sysdep(Close)(fd);
if (status < 0) /* announce that LoadElf failed */
printf("dl: Can't load %s\n", fullLibPath);
}
@ -431,7 +440,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
for (Elf_Half i = 0; i < header.e_phnum; i++)
{
ssize_t read = call_pread(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
ssize_t read = sysdep(PRead)(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
if (read != sizeof(Elf_Phdr))
{
printf("dl: Can't read program header %d\n", i);
@ -450,23 +459,23 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
off_t sectionOffset = ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
size_t sectionSize = ALIGN_UP(phdr.p_memsz + (phdr.p_vaddr - sectionOffset), phdr.p_align);
uintptr_t section = call_mmap(base + sectionOffset,
sectionSize, mmapProt,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
uintptr_t section = (uintptr_t)sysdep(MemoryMap)((void *)(base + sectionOffset),
sectionSize, mmapProt,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
sectionOffset = phdr.p_vaddr - ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
if (phdr.p_filesz > 0)
{
ssize_t read = call_pread(fd, section + sectionOffset, phdr.p_filesz, phdr.p_offset);
ssize_t read = sysdep(PRead)(fd, (void *)(section + sectionOffset), phdr.p_filesz, phdr.p_offset);
if (read != phdr.p_filesz)
{
printf("dl: Can't read segment %d in PT_LOAD\n", i);
@ -495,15 +504,15 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
{
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
dynamicTable = (Elf_Dyn *)call_mmap(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
dynamicTable = (Elf_Dyn *)sysdep(MemoryMap)(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
if ((intptr_t)dynamicTable <= 0)
{
@ -511,7 +520,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
return (int)(uintptr_t)dynamicTable;
}
read = call_pread(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
read = sysdep(PRead)(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
if (read != phdr.p_memsz)
{
printf("dl: Can't read PT_DYNAMIC\n");
@ -598,7 +607,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
}
Elf_Ehdr header;
call_pread(fd, &header, sizeof(Elf_Ehdr), 0);
sysdep(PRead)(fd, &header, sizeof(Elf_Ehdr), 0);
int status = CheckElfEhdr(&header, Path);
if (status != 0)
@ -606,11 +615,11 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
info = AllocateLib();
info->Header = header;
info->Path = (char *)call_mmap(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
__SYS_PROT_READ,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
-1, 0);
info->Path = (char *)sysdep(MemoryMap)(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
if ((intptr_t)info->Path <= 0)
{
printf("dl: Can't allocate memory for path\n");
@ -648,7 +657,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
if (status < 0)
{
call_munmap((uintptr_t)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
sysdep(MemoryUnmap)((void *)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
FreeLib(info);
return status;
}
@ -956,18 +965,18 @@ int _dl_main(int argc, char *argv[], char *envp[])
{
char *path = argv[0];
ElfInfo *info = NULL;
if (call_access(path, __SYS_F_OK) < 0)
if (sysdep(Access)(path, F_OK) < 0)
{
printf("dl: Can't access file %s\n", path);
return -EACCES;
}
int fd = call_open(path, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(path, O_RDONLY, 0644);
int status = LoadElf(fd, path, &info);
if (status < 0)
{
printf("%s: Can't load ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
@ -975,11 +984,11 @@ int _dl_main(int argc, char *argv[], char *envp[])
if (status < 0)
{
printf("%s: Can't relocate ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
call_close(fd);
sysdep(Close)(fd);
Elf_Addr entry = info->BaseAddress + info->Header.e_entry;
return ((int (*)(int, char *[], char *[]))entry)(argc, argv, envp);
}

View File

@ -1,4 +1,4 @@
/* nanoprintf v0.5.3: a tiny embeddable printf replacement written in C.
/* nanoprintf v0.5.4: a tiny embeddable printf replacement written in C.
https://github.com/charlesnicholson/nanoprintf
charles.nicholson+nanoprintf@gmail.com
dual-licensed under 0bsd and unlicense, take your pick. see eof for details. */
@ -336,6 +336,7 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
#if NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS == 1
out_spec->field_width = 0;
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_NONE;
if (*cur == '*')
{
@ -344,7 +345,6 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
else
{
out_spec->field_width = 0;
while ((*cur >= '0') && (*cur <= '9'))
{
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_LITERAL;

View File

@ -17,7 +17,8 @@
#include <stddef.h>
#include <stdarg.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/mman.h>
#include "elf.h"
#include "misc.h"
@ -31,7 +32,7 @@ void flush_buffer()
{
if (print_buffer_offset > 0)
{
call_write(1, print_buffer, print_buffer_offset);
sysdep(Write)(1, print_buffer, print_buffer_offset);
print_buffer_offset = 0;
}
}
@ -45,11 +46,11 @@ void print_wrapper(int c, void *)
void __init_print_buffer()
{
print_buffer = (char *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_PRIVATE | __SYS_MAP_ANONYMOUS,
-1, 0);
print_buffer = (char *)sysdep(MemoryMap)(0,
0x1000,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
print_buffer_size = 0x1000;
print_buffer_offset = 0;
}
@ -58,7 +59,7 @@ void __fini_print_buffer()
{
flush_buffer();
if (print_buffer != NULL)
call_munmap(print_buffer, 0x1000);
sysdep(MemoryUnmap)(print_buffer, 0x1000);
print_buffer = NULL;
}
@ -76,7 +77,7 @@ int puts(const char *s)
int len = strlen(s);
memcpy(print_buffer + print_buffer_offset, s, len);
print_buffer_offset += len;
print_buffer[print_buffer_offset++] = '\0';
print_buffer[print_buffer_offset++] = '\n';
flush_buffer();
return len + 1;
}

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
@ -97,54 +97,11 @@ const struct
void __init_print_buffer();
void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
#if defined(__amd64__)
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"call __init_print_buffer\n" /* Call __init_print_buffer */
"call _dl_preload\n" /* Call _dl_preload */
"movl %eax, %edi\n" /* Move return value to edi */
"cmp $0, %edi\n" /* Check if return value is 0 */
"jne _exit\n" /* If not, jump to _exit */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#elif defined(__arm__)
#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n");
#endif
sysdep(Exit)(status);
/* At this point, the program *SHOULD* have exited. */
__builtin_unreachable();
}

View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(FennixStandardLibraries)
add_subdirectory(libm)
add_subdirectory(libstdc++)

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
project(FennixMathLibrary)
set(SOURCES libm.c)
add_library(m STATIC ${SOURCES})
add_library(m_shared SHARED ${SOURCES})
target_link_options(m_shared PRIVATE -nostdlib)
set_target_properties(m_shared PROPERTIES OUTPUT_NAME "m")
install(TARGETS m m_shared
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)

Some files were not shown because too many files have changed in this diff Show More