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-bin \
grub-pc \ grub-pc \
grub2-common \ grub2-common \
pip pip \
cmake
# Install git-cliff # Install git-cliff
RUN pip install git-cliff --break-system-packages 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. // From this line below are for qemu, so not that important.
"mounts": [ "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": "/tmp/.X11-unix",
"source=/dev/kvm,target=/dev/kvm,type=bind,consistency=cached", "target": "/tmp/.X11-unix",
"source=/run/user/1000/pulse/native,target=/run/user/1000/pulse/native,type=bind,consistency=cached" "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": [ "runArgs": [
"--privileged" "--privileged"
] ],
// Features to add to the dev container. More info: https://containers.dev/features. "postAttachCommand": "sudo chmod 666 /dev/kvm"
// "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"
} }

View File

@ -19,3 +19,8 @@ indent_size = 2
[{CMakeLists.txt,*.cmake}] [{CMakeLists.txt,*.cmake}]
indent_size = 2 indent_size = 2
indent_style = space 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_LDFLAGS
export DRIVER_CFLAGS 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: build:
cp -rf ../Kernel/include/interface/* include/ cp -rf ../Kernel/include/interface/* include/
mkdir -p out mkdir -p out
make -C library build $(MAKE) -C library build
ifneq ($(filter amd64 i386,$(OSARCH)),) ifneq ($(filter amd64 i386,$(OSARCH)),)
make -C audio build $(MAKE) -C audio build
make -C input build $(MAKE) -C input build
make -C misc build $(MAKE) -C misc build
make -C network build $(MAKE) -C network build
make -C storage build $(MAKE) -C storage build
make -C filesystem build $(MAKE) -C filesystem build
endif endif
$(MAKE) copy_driver_signatures
prepare: prepare:
$(info Nothing to prepare) $(info Nothing to prepare)
clean: clean:
rm -rf out rm -rf out
make -C library clean $(MAKE) -C library clean
ifneq ($(filter amd64 i386,$(OSARCH)),) ifneq ($(filter amd64 i386,$(OSARCH)),)
make -C audio clean $(MAKE) -C audio clean
make -C input clean $(MAKE) -C input clean
make -C misc clean $(MAKE) -C misc clean
make -C network clean $(MAKE) -C network clean
make -C storage clean $(MAKE) -C storage clean
make -C filesystem clean $(MAKE) -C filesystem clean
endif endif

View File

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

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 */ /** Other: X */
#define S_IXOTH 0001 #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_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) #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/>. along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_API_SYSCALLS_LIST_H__ #ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_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 #pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum typedef enum
{ {
__SYS_O_RDONLY = 0x1, __SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = 0x2, __SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = 0x3, __SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = 0x4, __SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = 0x8, __SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = 0x10, __SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = 0x20, __SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = 0x40, __SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = 0x80, __SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = 0x100, __SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = 0x200, __SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = 0x400 __SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t; } syscall_open_flags_t;
typedef enum typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/ */
#define FBIOGET_SCREEN_INFO 0xf0 #define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/** /**
* @brief List of syscalls * @brief List of syscalls
* *
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid * - #EINVAL if the request is invalid
*/ */
SYS_IOCTL, 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 */ /* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied * - #EACCES if permission is denied
*/ */
SYS_RENAME, 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 * @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */ /** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp) #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 */ /* File Status */
/** @copydoc SYS_STAT */ /** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */ /** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath) #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", "git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false, "C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [ "conventionalCommits.scopes": [
"userspace",
"userspace/libc", "userspace/libc",
"vscode", "userspace/coreutils",
"userspace/apps/sys/init", "userspace/apps",
"userspace/libs/libm",
"devcontainer",
"userspace/libs", "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__ 1
#define KERNEL_NAME "Fennix" #define KERNEL_NAME "Fennix"
#define KERNEL_ARCH "amd64" #define KERNEL_ARCH "amd64"
#define KERNEL_VERSION "1.0" #define KERNEL_VERSION "1.0.0"
#define GIT_COMMIT "0000000000000000000000000000000000000000" #define GIT_COMMIT "0000000000000000000000000000000000000000"
#define GIT_COMMIT_SHORT "0000000" #define GIT_COMMIT_SHORT "0000000"

View File

@ -26,14 +26,48 @@
#include <exec.hpp> #include <exec.hpp>
#include <rand.hpp> #include <rand.hpp>
#include <cwalk.h> #include <cwalk.h>
#include <sha512.h>
#include <md5.h> #include <md5.h>
#include "../../kernel.h" #include "../../kernel.h"
using namespace vfs; using namespace vfs;
extern const char *trusted_drivers[];
extern const __SIZE_TYPE__ trusted_drivers_count;
namespace Driver 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() void Manager::PreloadDrivers()
{ {
debug("Initializing driver manager"); debug("Initializing driver manager");
@ -82,9 +116,19 @@ namespace Driver
if (!drvNode->IsRegularFile()) if (!drvNode->IsRegularFile())
continue; continue;
if (std::string(drvNode->Path).find(".drv") == std::string::npos)
continue;
if (Execute::GetBinaryType(drvNode->Path) != Execute::BinTypeELF) 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; 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 *devNode = nullptr;
FileNode *devInputNode = nullptr; FileNode *devInputNode = nullptr;
bool IsDriverTrusted(FileNode *File);
int LoadDriverFile(DriverObject &Drv, FileNode *File); int LoadDriverFile(DriverObject &Drv, FileNode *File);
void ReloadDriver(dev_t driverID); void ReloadDriver(dev_t driverID);

View File

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

@ -95,16 +95,6 @@
/** Other: X */ /** Other: X */
#define S_IXOTH 0001 #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_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) #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/>. along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_API_SYSCALLS_LIST_H__ #ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_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 #pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum typedef enum
{ {
__SYS_O_RDONLY = 0x1, __SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = 0x2, __SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = 0x3, __SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = 0x4, __SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = 0x8, __SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = 0x10, __SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = 0x20, __SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = 0x40, __SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = 0x80, __SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = 0x100, __SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = 0x200, __SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = 0x400 __SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t; } syscall_open_flags_t;
typedef enum typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/ */
#define FBIOGET_SCREEN_INFO 0xf0 #define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/** /**
* @brief List of syscalls * @brief List of syscalls
* *
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid * - #EINVAL if the request is invalid
*/ */
SYS_IOCTL, 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 */ /* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied * - #EACCES if permission is denied
*/ */
SYS_RENAME, 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 * @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */ /** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp) #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 */ /* File Status */
/** @copydoc SYS_STAT */ /** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */ /** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath) #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> #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__ #endif // !__FENNIX_KERNEL_STD_ERRNO_H__

View File

@ -412,79 +412,3 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
debug("Done."); debug("Done.");
} }
#pragma GCC diagnostic pop #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 KPrint(const char *Format, ...);
EXTERNC void Entry(struct BootInfo *Info); EXTERNC void Entry(struct BootInfo *Info);
EXTERNC void BeforeShutdown(bool Reboot); EXTERNC void BeforeShutdown(bool Reboot);
EXTERNC void TaskingPanic();
EXTERNC void KernelVFS(); EXTERNC void KernelVFS();
EXTERNC void KernelMainThread(); 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 int clockid_t;
typedef long time64_t; typedef long time64_t;
struct f_owner_ex struct linux_f_owner_ex
{ {
int type; int type;
pid_t pid; 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_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_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_fstat(SysFrm *Frame, int fd, struct stat *statbuf) { return -ENOSYS; }
static int sys_lstat(SysFrm *Frame, const char *pathname, 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); return fdt->usr_lseek(fd, offset, whence);
} }
static __noreturn void sys_exit(SysFrm *Frame, int status) __noreturn void sys_exit(SysFrm *Frame, int status);
{ pid_t sys_fork(SysFrm *Frame);
TCB *t = thisThread; int sys_execve(SysFrm *Frame, const char *pathname, char *const argv[], char *const envp[]);
{ pid_t sys_getpid(SysFrm *Frame);
CriticalSection cs; pid_t sys_getppid(SysFrm *Frame);
trace("Userspace thread %s(%d) exited with code %d (%#x)", pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
t->Name, int sys_kill(SysFrm *Frame, pid_t pid, int sig);
t->ID, status, int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4);
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;
}
}
int sys_brk(SysFrm *Frame, void *end_data); 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); 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_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_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] = {}; static SyscallData scTbl[SYS_MAX] = {};
__constructor void __init_native_syscalls(void) __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_OPEN] = {"SYS_OPEN", (void *)sys_open};
scTbl[SYS_CLOSE] = {"SYS_CLOSE", (void *)sys_close}; scTbl[SYS_CLOSE] = {"SYS_CLOSE", (void *)sys_close};
scTbl[SYS_IOCTL] = {"SYS_IOCTL", (void *)sys_ioctl}; scTbl[SYS_IOCTL] = {"SYS_IOCTL", (void *)sys_ioctl};
scTbl[SYS_FCNTL] = {"SYS_FCNTL", (void *)sys_fcntl};
/* File Status */ /* File Status */
scTbl[SYS_STAT] = {"SYS_STAT", (void *)sys_stat}; 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_RMDIR] = {"SYS_RMDIR", (void *)sys_rmdir};
scTbl[SYS_UNLINK] = {"SYS_UNLINK", (void *)sys_unlink}; scTbl[SYS_UNLINK] = {"SYS_UNLINK", (void *)sys_unlink};
scTbl[SYS_RENAME] = {"SYS_RENAME", (void *)sys_rename}; scTbl[SYS_RENAME] = {"SYS_RENAME", (void *)sys_rename};
scTbl[SYS_UNAME] = {"SYS_UNAME", (void *)sys_uname};
} }
uintptr_t HandleNativeSyscalls(SysFrm *Frame) 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) prepare
$(MAKE) tools $(MAKE) tools
setup-no-qemu:
$(MAKE) --quiet -C tools ci
build: build_kernel build_bootloader build_userspace build_drivers build_image build: build_kernel build_bootloader build_userspace build_drivers build_image
dump: dump:
@ -313,6 +316,8 @@ endif
vscode_debug: build_kernel build_userspace build_drivers build_image vscode_debug_only vscode_debug: build_kernel build_userspace build_drivers build_image vscode_debug_only
debug: vscode_debug
qemu: qemu_vdisk clean_logs qemu: qemu_vdisk clean_logs
touch serial.log touch serial.log
# x-terminal-emulator -e tail -f serial.log & # x-terminal-emulator -e tail -f serial.log &

View File

@ -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. 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 Check out the [installation guide](INSTALL.md) to compile the project from source.
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.
## 📚 Documentation ## 📚 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: To generate the documentation, run:
```sh ```sh

View File

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

View File

@ -160,5 +160,30 @@
"*/" "*/"
], ],
"description": "Create libc license." "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)", "name": "Fennix x64 (Linux, GCC, debug)",
"includePath": [ "includePath": [
"${workspaceFolder}/libc/include/**", "${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**" "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
], ],
"defines": [ "defines": [
"__debug_vscode__", "__debug_vscode__",
"DEBUG=\"1\"" "DEBUG=\"1\""
], ],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc", "compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc",
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",
@ -45,12 +50,17 @@
"name": "Fennix x32 (Linux, GCC, debug)", "name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [ "includePath": [
"${workspaceFolder}/libc/include/**", "${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**" "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
], ],
"defines": [ "defines": [
"__debug_vscode__", "__debug_vscode__",
"DEBUG=\"1\"" "DEBUG=\"1\""
], ],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc", "compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-fennix-gcc",
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",
@ -86,12 +96,17 @@
"name": "Fennix Arm (Linux, GCC, debug)", "name": "Fennix Arm (Linux, GCC, debug)",
"includePath": [ "includePath": [
"${workspaceFolder}/libc/include/**", "${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**" "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
], ],
"defines": [ "defines": [
"__debug_vscode__", "__debug_vscode__",
"DEBUG=\"1\"" "DEBUG=\"1\""
], ],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc", "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc",
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",
@ -107,12 +122,17 @@
"name": "Fennix Aarch64 (Linux, GCC, debug)", "name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [ "includePath": [
"${workspaceFolder}/libc/include/**", "${workspaceFolder}/libc/include/**",
"${workspaceFolder}/libs/include/**" "${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**",
"${workspaceFolder}/out/include/**"
], ],
"defines": [ "defines": [
"__debug_vscode__", "__debug_vscode__",
"DEBUG=\"1\"" "DEBUG=\"1\""
], ],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc", "compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-fennix-gcc",
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",

View File

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

View File

@ -1,5 +1,6 @@
{ {
"git.openRepositoryInParentFolders": "always", "git.openRepositoryInParentFolders": "always",
"git.alwaysSignOff": true, "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

@ -37,9 +37,42 @@ create_out:
mkdir -p out/usr/include 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 build: create_out
make -C libc build $(MAKE) build_libc
make -C libs build make -C libs build
$(MAKE) build_coreutils
make -C apps build make -C apps build
prepare: prepare:
@ -49,6 +82,6 @@ clean:
rm -rf out cache rm -rf out cache
mkdir -p cache mkdir -p cache
touch cache/.gitkeep touch cache/.gitkeep
make -C libc clean
make -C libs clean make -C libs clean
make -C apps 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 #endif
} }
volatile int __dummy = 0;
int fill_stack(void *p) 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); 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 WARNCFLAG = -Wall -Wextra
build: $(FILENAME).elf build: $(FILENAME).elf
cp $(FILENAME).elf $(WORKSPACE_DIR)/out/bin/$(FILENAME) cp $(FILENAME).elf $(WORKSPACE_DIR)/out/usr/bin/$(FILENAME)
$(FILENAME).elf: $(OBJ) $(FILENAME).elf: $(OBJ)
$(info Linking $@) $(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/>. along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_API_SYSCALLS_LIST_H__ #ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_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 #pragma region Syscall Wrappers
@ -393,18 +403,18 @@ typedef enum
typedef enum typedef enum
{ {
__SYS_O_RDONLY = 0x1, __SYS_O_RDONLY = O_RDONLY,
__SYS_O_WRONLY = 0x2, __SYS_O_WRONLY = O_WRONLY,
__SYS_O_RDWR = 0x3, __SYS_O_RDWR = O_RDWR,
__SYS_O_APPEND = 0x4, __SYS_O_APPEND = O_APPEND,
__SYS_O_CREAT = 0x8, __SYS_O_CREAT = O_CREAT,
__SYS_O_DSYNC = 0x10, __SYS_O_DSYNC = O_DSYNC,
__SYS_O_EXCL = 0x20, __SYS_O_EXCL = O_EXCL,
__SYS_O_NOCTTY = 0x40, __SYS_O_NOCTTY = O_NOCTTY,
__SYS_O_NONBLOCK = 0x80, __SYS_O_NONBLOCK = O_NONBLOCK,
__SYS_O_RSYNC = 0x100, __SYS_O_RSYNC = O_RSYNC,
__SYS_O_SYNC = 0x200, __SYS_O_SYNC = O_SYNC,
__SYS_O_TRUNC = 0x400 __SYS_O_TRUNC = O_TRUNC
} syscall_open_flags_t; } syscall_open_flags_t;
typedef enum typedef enum
@ -624,6 +634,14 @@ typedef struct FramebufferScreenInfo
*/ */
#define FBIOGET_SCREEN_INFO 0xf0 #define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/** /**
* @brief List of syscalls * @brief List of syscalls
* *
@ -812,6 +830,25 @@ typedef enum
* - #EINVAL if the request is invalid * - #EINVAL if the request is invalid
*/ */
SYS_IOCTL, 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 */ /* File Status */
@ -1601,6 +1638,22 @@ typedef enum
* - #EACCES if permission is denied * - #EACCES if permission is denied
*/ */
SYS_RENAME, 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 * @brief Max number of syscalls
@ -1644,6 +1697,9 @@ typedef enum
/** @copydoc SYS_IOCTL */ /** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp) #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 */ /* File Status */
/** @copydoc SYS_STAT */ /** @copydoc SYS_STAT */
@ -1782,4 +1838,7 @@ typedef enum
/** @copydoc SYS_RENAME */ /** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath) #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 modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. 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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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__ #ifndef _ERRNO_H
#define __FENNIX_API_ERRNO_H__ #define _ERRNO_H
/** #include <bits/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;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -602,4 +34,4 @@ extern "C"
#define errno (*__errno_location()) #define errno (*__errno_location())
#endif // !__FENNIX_API_ERRNO_H__ #endif // _ERRNO_H

View File

@ -24,77 +24,7 @@ extern "C"
#endif // __cplusplus #endif // __cplusplus
#include <sys/types.h> #include <sys/types.h>
#include <bits/fcntl.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
int creat(const char *path, mode_t mode); int creat(const char *path, mode_t mode);
int fcntl(int fildes, int cmd, ...); 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 y1(double x);
double yn(int n, 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 #ifdef __cplusplus
} }
#endif // __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 #endif // __cplusplus
#include <sys/types.h> #include <sys/types.h>
#include <fennix/syscalls.h> #include <bits/libc.h>
#include <bits/types/timespec.h> #include <bits/types/timespec.h>
#define SIGNULL __SYS_SIGNULL #include <bits/signal.h>
#define SIGABRT __SYS_SIGABRT #include <bits/types/signal.h>
#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. */
};
typedef struct siginfo_t typedef struct siginfo_t
{ {
@ -149,15 +45,6 @@ extern "C"
union sigval si_value; /* Signal value. */ union sigval si_value; /* Signal value. */
} siginfo_t; } 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 struct sigaction
{ {
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */ 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 #ifndef _SYS_IOCTL_H
#define _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, ...); int ioctl(int fd, unsigned long op, ...);

View File

@ -21,15 +21,26 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.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; typedef unsigned int sa_family_t;
#endif
#ifndef __sockaddr_defined
#define __sockaddr_defined
struct sockaddr struct sockaddr
{ {
sa_family_t sa_family; sa_family_t sa_family;
char sa_data[14]; char sa_data[14];
}; };
#endif
#define _SS_MAXSIZE 128 #define _SS_MAXSIZE 128
#define _SS_ALIGNSIZE (sizeof(int64_t)) #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. */ blkcnt_t st_blocks; /* Number of blocks allocated for this object. */
}; };
#define S_IFMT #define S_IFMT 0170000
#define S_IFBLK #define S_IFBLK 0060000
#define S_IFCHR #define S_IFCHR 0020000
#define S_IFIFO #define S_IFIFO 0010000
#define S_IFREG #define S_IFREG 0100000
#define S_IFDIR #define S_IFDIR 0040000
#define S_IFLNK #define S_IFLNK 0120000
#define S_IFSOCK #define S_IFSOCK 0140000
#define S_IRWXU 0700 #define S_IRWXU 0700
#define S_IRUSR 0400 #define S_IRUSR 0400
@ -68,21 +68,21 @@ extern "C"
#define S_ISGID 02000 #define S_ISGID 02000
#define S_ISVTX 01000 #define S_ISVTX 01000
#define S_ISBLK(m) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISCHR(m) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISDIR(m) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISREG(m) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISLNK(m) #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_TYPEISMQ(buf) #define S_TYPEISMQ(buf) 0
#define S_TYPEISSEM(buf) #define S_TYPEISSEM(buf) 0
#define S_TYPEISSHM(buf) #define S_TYPEISSHM(buf) 0
#define S_TYPEISTMO(buf) #define S_TYPEISTMO(buf) 0
#define UTIME_NOW #define UTIME_NOW 0x3fffffff
#define UTIME_OMIT #define UTIME_OMIT 0x3ffffffe
int chmod(const char *, mode_t); int chmod(const char *, mode_t);
int fchmod(int, mode_t); int fchmod(int, mode_t);

View File

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

View File

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

View File

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

View File

@ -59,10 +59,10 @@ extern "C"
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
extern char **environ; extern char **environ;
int access(const char *, int); int access(const char *path, int amode);
unsigned int alarm(unsigned int seconds); unsigned int alarm(unsigned int seconds);
int brk(void *); int brk(void *addr);
int chdir(const char *); int chdir(const char *path);
int chroot(const char *); int chroot(const char *);
int chown(const char *, uid_t, gid_t); int chown(const char *, uid_t, gid_t);
int close(int fildes); int close(int fildes);
@ -87,7 +87,7 @@ extern "C"
long int fpathconf(int, int); long int fpathconf(int, int);
int fsync(int); int fsync(int);
int ftruncate(int, off_t); int ftruncate(int, off_t);
char *getcwd(char *, size_t); char *getcwd(char *buf, size_t size);
int getdtablesize(void); int getdtablesize(void);
gid_t getegid(void); gid_t getegid(void);
uid_t geteuid(void); uid_t geteuid(void);
@ -122,7 +122,7 @@ extern "C"
ssize_t read(int fildes, void *buf, size_t nbyte); ssize_t read(int fildes, void *buf, size_t nbyte);
int readlink(const char *, char *, size_t); int readlink(const char *, char *, size_t);
int rmdir(const char *); int rmdir(const char *);
void *sbrk(intptr_t); void *sbrk(intptr_t incr);
int setgid(gid_t); int setgid(gid_t);
int setpgid(pid_t, pid_t); int setpgid(pid_t, pid_t);
pid_t setpgrp(void); 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/>. 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/types.h>
#include <sys/mman.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <errno.h> #include <errno.h>
@ -39,7 +40,7 @@ MemoryBlock *memory_pool = NULL;
void *request_page(size_t size) void *request_page(size_t size)
{ {
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 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) if ((intptr_t)addr < 0)
return NULL; return NULL;
return addr; return addr;
@ -48,7 +49,7 @@ void *request_page(size_t size)
void free_page(void *addr, size_t size) void free_page(void *addr, size_t size)
{ {
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 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) 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/>. 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/types.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>

View File

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

View File

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

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>. 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"; // const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
@ -97,54 +97,11 @@ const struct
void __init_print_buffer(); void __init_print_buffer();
void __fini_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) __attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{ {
__fini_print_buffer(); __fini_print_buffer();
call_exit(status); sysdep(Exit)(status);
/* At this point, the program *SHOULD* have exited. */ /* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n");
#endif
__builtin_unreachable(); __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)

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
project(FennixStandardC++Library)
set(SOURCES libstdc++.cpp)
add_library(stdc++ STATIC ${SOURCES})
add_library(stdc++_shared SHARED ${SOURCES})
target_link_options(stdc++_shared PRIVATE -nostdlib)
set_target_properties(stdc++_shared PROPERTIES OUTPUT_NAME "stdc++")
install(TARGETS stdc++ stdc++_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