feat: Add signals, exec/wait, and FD/pipe support

Introduce process lifecycle and POSIX-like features: add parent_pid, pgid, exited/exit_status, signal state and handlers, waitpid/reap, and an exec-replace function. Refactor file descriptor handling to use fd_kind/fd_flags with reference-counted file refs and in-process pipes; implement open/read/write/close/seek/tell/size/dup/dup2/pipe/fcntl semantics and O_* flags. Add syscall handlers for exec, waitpid, kill/signal, sigaction, sigprocmask, sigpending, meminfo/ticks and map many SYSTEM_CMD_* constants; deliver signals from the syscall path. Cleanup/terminate logic updated to free resources correctly and initialize kernel/user processes with new state. Misc: minor syscall/table renames (wallpaper), helper utilities (process_close_fd_inner, process_init_signal_state) and paging/stack handling for exec.
This commit is contained in:
boreddevnl
2026-04-20 00:03:52 +02:00
parent ae8c7e21ac
commit af5eda1647
35 changed files with 2234 additions and 208 deletions

View File

@@ -4,6 +4,7 @@
extern int errno;
#define EDOM 33
#define E2BIG 7
#define ERANGE 34
#define EINVAL 22
#define EISDIR 21
@@ -13,6 +14,14 @@ extern int errno;
#define EBADF 9
#define EIO 5
#define EEXIST 17
#define EAGAIN 11
#define EINTR 4
#define ECHILD 10
#define ENOTSUP 95
#define EPIPE 32
#define ENOTDIR 20
#define EBUSY 16
#define ESPIPE 29
#define ENOSYS 38
#endif

View File

@@ -6,10 +6,22 @@
#define O_RDONLY 0x0000
#define O_WRONLY 0x0001
#define O_RDWR 0x0002
#define O_ACCMODE 0x0003
#define O_CREAT 0x0040
#define O_EXCL 0x0080
#define O_TRUNC 0x0200
#define O_APPEND 0x0400
#define O_NONBLOCK 0x0800
#define F_GETFL 3
#define F_SETFL 4
#define FD_CLOEXEC 1
int open(const char *pathname, int flags, ...);
int fcntl(int fd, int cmd, ...);
int dup(int oldfd);
int dup2(int oldfd, int newfd);
int pipe(int pipefd[2]);
#endif

View File

@@ -10,7 +10,6 @@ extern uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_
// sys_gui uses syscall #3
#define SYS_GUI 3
#define GUI_CMD_GET_SCREEN_SIZE 17
ui_window_t ui_window_create(const char *title, int x, int y, int w, int h) {
uint64_t params[4] = { (uint64_t)x, (uint64_t)y, (uint64_t)w, (uint64_t)h };

View File

@@ -22,6 +22,10 @@
#define GUI_CMD_WINDOW_SET_TITLE 15
#define GUI_CMD_SET_FONT 16
#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18
#define GUI_CMD_GET_SCREEN_SIZE 50
#define GUI_CMD_GET_SCREENBUFFER 51
#define GUI_CMD_SHOW_NOTIFICATION 52
#define GUI_CMD_GET_DATETIME 53
// Event Types
#define GUI_EVENT_NONE 0

View File

@@ -2,12 +2,32 @@
#include "syscall.h"
#include "sys/stat.h"
static void _b_stat_init(struct stat *st) {
st->st_dev = 0;
st->st_ino = 0;
st->st_mode = 0;
st->st_nlink = 1;
st->st_uid = 0;
st->st_gid = 0;
st->st_rdev = 0;
st->st_size = 0;
st->st_blksize = 512;
st->st_blocks = 0;
st->st_atime = 0;
st->st_mtime = 0;
st->st_ctime = 0;
}
__attribute__((weak)) int mkdir(const char *pathname, int mode) {
(void)mode;
if (!pathname || pathname[0] == '\0') {
errno = EINVAL;
return -1;
}
if (sys_exists(pathname)) {
errno = EEXIST;
return -1;
}
if (sys_mkdir(pathname) == 0) {
return 0;
}
@@ -29,6 +49,7 @@ __attribute__((weak)) int access(const char *pathname, int mode) {
}
__attribute__((weak)) int stat(const char *pathname, struct stat *statbuf) {
FAT32_FileInfo info;
if (!pathname || pathname[0] == '\0') {
errno = EINVAL;
return -1;
@@ -39,14 +60,27 @@ __attribute__((weak)) int stat(const char *pathname, struct stat *statbuf) {
}
if (statbuf) {
int fd = sys_open(pathname, "rb");
if (fd >= 0) {
statbuf->st_size = (int)sys_size(fd);
sys_close(fd);
_b_stat_init(statbuf);
if (sys_get_file_info(pathname, &info) == 0) {
statbuf->st_size = (int)info.size;
if (info.is_directory) {
statbuf->st_mode = S_IFDIR | 0755;
} else {
statbuf->st_mode = S_IFREG | 0644;
}
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
} else {
statbuf->st_size = 0;
int fd = sys_open(pathname, "rb");
if (fd >= 0) {
statbuf->st_size = (int)sys_size(fd);
statbuf->st_mode = S_IFREG | 0644;
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
sys_close(fd);
} else {
errno = EIO;
return -1;
}
}
statbuf->st_mode = 0;
}
return 0;

View File

@@ -1,14 +1,98 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include "errno.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "sys/stat.h"
#include "syscall.h"
#include "unistd.h"
#define POSIX_MAX_FDS 256
#define PIPE_BUF_SIZE 4096
typedef enum {
HANDLE_UNUSED = 0,
HANDLE_KERNEL_FD,
HANDLE_PIPE_READ,
HANDLE_PIPE_WRITE
} handle_type_t;
typedef struct {
unsigned char data[PIPE_BUF_SIZE];
size_t read_pos;
size_t write_pos;
size_t count;
int readers;
int writers;
} pipe_state_t;
typedef struct {
handle_type_t type;
int refcount;
int flags;
int kernel_fd;
pipe_state_t *pipe;
} fd_handle_t;
static fd_handle_t *g_fd_table[POSIX_MAX_FDS];
static fd_handle_t g_stdio_handles[3];
static int g_fd_initialized = 0;
static void _b_fd_init(void) {
int i;
if (g_fd_initialized) {
return;
}
for (i = 0; i < POSIX_MAX_FDS; i++) {
g_fd_table[i] = NULL;
}
for (i = 0; i < 3; i++) {
g_stdio_handles[i].type = HANDLE_KERNEL_FD;
g_stdio_handles[i].refcount = 1;
g_stdio_handles[i].flags = O_RDWR;
g_stdio_handles[i].kernel_fd = i;
g_stdio_handles[i].pipe = NULL;
g_fd_table[i] = &g_stdio_handles[i];
}
g_fd_initialized = 1;
}
static int _b_alloc_fd_from(int start) {
int fd;
for (fd = start; fd < POSIX_MAX_FDS; fd++) {
if (g_fd_table[fd] == NULL) {
return fd;
}
}
return -1;
}
static fd_handle_t *_b_get_handle(int fd) {
if (fd < 0 || fd >= POSIX_MAX_FDS) {
return NULL;
}
return g_fd_table[fd];
}
static void _b_reset_stat_common(struct stat *st) {
memset(st, 0, sizeof(*st));
st->st_blksize = 512;
}
static int _b_fill_kernel_fstat(int kfd, struct stat *statbuf) {
_b_reset_stat_common(statbuf);
statbuf->st_mode = (kfd <= 2) ? (S_IFCHR | 0666) : (S_IFREG | 0644);
statbuf->st_size = (kfd <= 2) ? 0 : (int)sys_size(kfd);
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
statbuf->st_nlink = 1;
return 0;
}
static const char *_b_mode_from_flags(int flags) {
int accmode = (flags & O_RDWR) ? O_RDWR : ((flags & O_WRONLY) ? O_WRONLY : O_RDONLY);
int accmode = flags & O_ACCMODE;
if (accmode == O_RDONLY) {
return "rb";
@@ -18,7 +102,7 @@ static const char *_b_mode_from_flags(int flags) {
if (flags & O_TRUNC) {
return "w+";
}
if (flags & O_CREAT) {
if (flags & O_APPEND) {
return "a+";
}
return "r+";
@@ -30,57 +114,224 @@ static const char *_b_mode_from_flags(int flags) {
if (flags & O_TRUNC) {
return "wb";
}
if (flags & O_CREAT) {
return "wb";
}
return "wb";
}
static int _b_pipe_read(fd_handle_t *h, void *buf, size_t count) {
size_t n = 0;
pipe_state_t *p = h->pipe;
unsigned char *out = (unsigned char *)buf;
if (!p || !buf) {
errno = EINVAL;
return -1;
}
while (n < count) {
if (p->count == 0) {
if (p->writers == 0) {
break;
}
if (h->flags & O_NONBLOCK) {
if (n == 0) {
errno = EAGAIN;
return -1;
}
break;
}
sys_yield();
continue;
}
out[n++] = p->data[p->read_pos];
p->read_pos = (p->read_pos + 1) % PIPE_BUF_SIZE;
p->count--;
}
return (int)n;
}
static int _b_pipe_write(fd_handle_t *h, const void *buf, size_t count) {
size_t n = 0;
pipe_state_t *p = h->pipe;
const unsigned char *in = (const unsigned char *)buf;
if (!p || !buf) {
errno = EINVAL;
return -1;
}
if (p->readers == 0) {
errno = EPIPE;
return -1;
}
while (n < count) {
if (p->count == PIPE_BUF_SIZE) {
if (h->flags & O_NONBLOCK) {
if (n == 0) {
errno = EAGAIN;
return -1;
}
break;
}
sys_yield();
continue;
}
p->data[p->write_pos] = in[n++];
p->write_pos = (p->write_pos + 1) % PIPE_BUF_SIZE;
p->count++;
}
return (int)n;
}
__attribute__((weak)) int open(const char *pathname, int flags, ...) {
int fd;
int kfd;
int exists;
mode_t mode = 0;
fd_handle_t *h;
_b_fd_init();
if (!pathname || pathname[0] == '\0') {
errno = EINVAL;
return -1;
}
if (flags & O_CREAT) {
va_list ap;
(void)ap;
va_start(ap, flags);
(void)va_arg(ap, int);
va_end(ap);
if ((flags & O_ACCMODE) > O_RDWR) {
errno = EINVAL;
return -1;
}
fd = sys_open(pathname, _b_mode_from_flags(flags));
if (fd < 0) {
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) == O_RDONLY)) {
errno = EINVAL;
return -1;
}
exists = sys_exists(pathname);
if ((flags & O_CREAT) && (flags & O_EXCL) && exists) {
errno = EEXIST;
return -1;
}
if (!(flags & O_CREAT) && !exists) {
errno = ENOENT;
return -1;
}
if (flags & O_CREAT) {
va_list ap;
va_start(ap, flags);
mode = (mode_t)va_arg(ap, int);
va_end(ap);
(void)mode;
}
kfd = sys_open(pathname, _b_mode_from_flags(flags));
if (kfd < 0) {
errno = EIO;
return -1;
}
h = (fd_handle_t *)malloc(sizeof(fd_handle_t));
if (!h) {
sys_close(kfd);
errno = ENOMEM;
return -1;
}
fd = _b_alloc_fd_from(3);
if (fd < 0) {
free(h);
sys_close(kfd);
errno = EBUSY;
return -1;
}
h->type = HANDLE_KERNEL_FD;
h->refcount = 1;
h->flags = flags;
h->kernel_fd = kfd;
h->pipe = NULL;
g_fd_table[fd] = h;
if (flags & O_APPEND) {
(void)sys_seek(fd, 0, SEEK_END);
(void)sys_seek(kfd, 0, SEEK_END);
}
return fd;
}
__attribute__((weak)) int close(int fd) {
if (fd < 0) {
fd_handle_t *h;
_b_fd_init();
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
sys_close(fd);
g_fd_table[fd] = NULL;
if (--h->refcount > 0) {
return 0;
}
if (h->type == HANDLE_KERNEL_FD) {
if (h->kernel_fd >= 3) {
sys_close(h->kernel_fd);
}
} else if (h->type == HANDLE_PIPE_READ || h->type == HANDLE_PIPE_WRITE) {
pipe_state_t *p = h->pipe;
if (p) {
if (h->type == HANDLE_PIPE_READ) {
p->readers--;
} else {
p->writers--;
}
if (p->readers <= 0 && p->writers <= 0) {
free(p);
}
}
}
if (h < &g_stdio_handles[0] || h > &g_stdio_handles[2]) {
free(h);
}
return 0;
}
__attribute__((weak)) ssize_t read(int fd, void *buf, size_t count) {
fd_handle_t *h;
int n;
if (fd < 0 || (!buf && count != 0)) {
_b_fd_init();
if (!buf && count != 0) {
errno = EINVAL;
return -1;
}
n = sys_read(fd, buf, (uint32_t)count);
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
if (h->type == HANDLE_PIPE_WRITE) {
errno = EBADF;
return -1;
}
if (h->type == HANDLE_PIPE_READ) {
n = _b_pipe_read(h, buf, count);
return (ssize_t)n;
}
n = sys_read(h->kernel_fd, buf, (uint32_t)count);
if (n < 0) {
errno = EIO;
return -1;
@@ -89,16 +340,35 @@ __attribute__((weak)) ssize_t read(int fd, void *buf, size_t count) {
}
__attribute__((weak)) ssize_t write(int fd, const void *buf, size_t count) {
fd_handle_t *h;
int n;
if (fd < 0 || (!buf && count != 0)) {
_b_fd_init();
if (!buf && count != 0) {
errno = EINVAL;
return -1;
}
if (fd <= 2) {
n = sys_write(fd, (const char *)buf, (int)count);
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
if (h->type == HANDLE_PIPE_READ) {
errno = EBADF;
return -1;
}
if (h->type == HANDLE_PIPE_WRITE) {
n = _b_pipe_write(h, buf, count);
return (ssize_t)n;
}
if (h->kernel_fd <= 2) {
n = sys_write(h->kernel_fd, (const char *)buf, (int)count);
} else {
n = sys_write_fs(fd, buf, (uint32_t)count);
n = sys_write_fs(h->kernel_fd, buf, (uint32_t)count);
}
if (n < 0) {
@@ -109,20 +379,28 @@ __attribute__((weak)) ssize_t write(int fd, const void *buf, size_t count) {
}
__attribute__((weak)) off_t lseek(int fd, off_t offset, int whence) {
if (fd < 0) {
fd_handle_t *h;
_b_fd_init();
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
if (h->type != HANDLE_KERNEL_FD) {
errno = ESPIPE;
return -1;
}
if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
errno = EINVAL;
return -1;
}
if (sys_seek(fd, (int)offset, whence) < 0) {
if (sys_seek(h->kernel_fd, (int)offset, whence) < 0) {
errno = EIO;
return -1;
}
return (off_t)sys_tell(fd);
return (off_t)sys_tell(h->kernel_fd);
}
__attribute__((weak)) int unlink(const char *pathname) {
@@ -138,16 +416,235 @@ __attribute__((weak)) int unlink(const char *pathname) {
}
__attribute__((weak)) int isatty(int fd) {
return (fd >= 0 && fd <= 2) ? 1 : 0;
fd_handle_t *h;
_b_fd_init();
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return 0;
}
return (h->type == HANDLE_KERNEL_FD && h->kernel_fd <= 2) ? 1 : 0;
}
__attribute__((weak)) int fstat(int fd, struct stat *statbuf) {
if (fd < 0 || !statbuf) {
fd_handle_t *h;
_b_fd_init();
if (!statbuf) {
errno = EINVAL;
return -1;
}
statbuf->st_size = (int)sys_size(fd);
statbuf->st_mode = 0;
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
if (h->type == HANDLE_PIPE_READ || h->type == HANDLE_PIPE_WRITE) {
_b_reset_stat_common(statbuf);
statbuf->st_mode = S_IFIFO | 0666;
statbuf->st_size = (int)(h->pipe ? h->pipe->count : 0);
return 0;
}
return _b_fill_kernel_fstat(h->kernel_fd, statbuf);
}
__attribute__((weak)) int dup(int oldfd) {
fd_handle_t *h;
int newfd;
int newkfd;
_b_fd_init();
h = _b_get_handle(oldfd);
if (!h) {
errno = EBADF;
return -1;
}
if (h->type != HANDLE_KERNEL_FD) {
errno = ENOTSUP;
return -1;
}
newkfd = sys_dup(h->kernel_fd);
if (newkfd < 0) {
errno = EBADF;
return -1;
}
newfd = _b_alloc_fd_from(0);
if (newfd < 0) {
sys_close(newkfd);
errno = EBUSY;
return -1;
}
h = (fd_handle_t *)malloc(sizeof(fd_handle_t));
if (!h) {
sys_close(newkfd);
errno = ENOMEM;
return -1;
}
h->type = HANDLE_KERNEL_FD;
h->refcount = 1;
h->flags = O_RDWR;
h->kernel_fd = newkfd;
h->pipe = NULL;
g_fd_table[newfd] = h;
return newfd;
}
__attribute__((weak)) int dup2(int oldfd, int newfd) {
fd_handle_t *h;
fd_handle_t *nh;
int newkfd;
_b_fd_init();
h = _b_get_handle(oldfd);
if (!h || newfd < 0 || newfd >= POSIX_MAX_FDS) {
errno = EBADF;
return -1;
}
if (oldfd == newfd) {
return newfd;
}
if (h->type != HANDLE_KERNEL_FD) {
errno = ENOTSUP;
return -1;
}
if (g_fd_table[newfd]) {
if (close(newfd) != 0) {
return -1;
}
}
newkfd = sys_dup(h->kernel_fd);
if (newkfd < 0) {
errno = EBADF;
return -1;
}
nh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
if (!nh) {
errno = ENOMEM;
return -1;
}
nh->type = HANDLE_KERNEL_FD;
nh->refcount = 1;
nh->flags = h->flags;
nh->kernel_fd = newkfd;
nh->pipe = NULL;
g_fd_table[newfd] = nh;
return newfd;
}
__attribute__((weak)) int pipe(int pipefd[2]) {
fd_handle_t *rh;
fd_handle_t *wh;
int rfd;
int wfd;
int kpipe[2];
_b_fd_init();
if (!pipefd) {
errno = EINVAL;
return -1;
}
if (sys_pipe(kpipe) < 0) {
errno = EIO;
return -1;
}
rfd = _b_alloc_fd_from(3);
if (rfd < 0) {
sys_close(kpipe[0]);
sys_close(kpipe[1]);
errno = EBUSY;
return -1;
}
wfd = _b_alloc_fd_from(rfd + 1);
if (wfd < 0) {
sys_close(kpipe[0]);
sys_close(kpipe[1]);
errno = EBUSY;
return -1;
}
rh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
wh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
if (!rh || !wh) {
free(rh);
free(wh);
sys_close(kpipe[0]);
sys_close(kpipe[1]);
errno = ENOMEM;
return -1;
}
rh->type = HANDLE_KERNEL_FD;
rh->refcount = 1;
rh->flags = O_RDONLY;
rh->kernel_fd = kpipe[0];
rh->pipe = NULL;
wh->type = HANDLE_KERNEL_FD;
wh->refcount = 1;
wh->flags = O_WRONLY;
wh->kernel_fd = kpipe[1];
wh->pipe = NULL;
g_fd_table[rfd] = rh;
g_fd_table[wfd] = wh;
pipefd[0] = rfd;
pipefd[1] = wfd;
return 0;
}
__attribute__((weak)) int fcntl(int fd, int cmd, ...) {
fd_handle_t *h;
va_list ap;
int val;
_b_fd_init();
h = _b_get_handle(fd);
if (!h) {
errno = EBADF;
return -1;
}
switch (cmd) {
case F_GETFL:
if (h->type == HANDLE_KERNEL_FD) {
int k = sys_fcntl(h->kernel_fd, cmd, 0);
if (k < 0) {
errno = ENOSYS;
return -1;
}
h->flags = k;
}
return h->flags;
case F_SETFL:
va_start(ap, cmd);
val = va_arg(ap, int);
va_end(ap);
if (h->type == HANDLE_KERNEL_FD) {
if (sys_fcntl(h->kernel_fd, cmd, val) < 0) {
errno = ENOSYS;
return -1;
}
}
h->flags = (h->flags & ~(O_APPEND | O_NONBLOCK)) | (val & (O_APPEND | O_NONBLOCK));
return 0;
default:
errno = ENOSYS;
return -1;
}
}

View File

@@ -0,0 +1,224 @@
#include <stdarg.h>
#include <stddef.h>
#include "errno.h"
#include "stdio.h"
#include "string.h"
#include "sys/types.h"
#include "sys/wait.h"
#include "syscall.h"
#include "unistd.h"
static int _b_is_space(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
}
static int _b_path_exists(const char *path) {
return path && path[0] && sys_exists(path);
}
static const char *_b_resolve_exec_path(const char *file, char *out, size_t cap) {
if (!file || !file[0]) {
return NULL;
}
if (file[0] == '/') {
return _b_path_exists(file) ? file : NULL;
}
snprintf(out, cap, "/bin/%s", file);
if (_b_path_exists(out)) {
return out;
}
snprintf(out, cap, "/bin/%s.elf", file);
if (_b_path_exists(out)) {
return out;
}
return NULL;
}
static int _b_join_argv(char *buf, size_t cap, char *const argv[]) {
size_t used = 0;
if (!argv || !argv[0]) {
if (cap) {
buf[0] = '\0';
}
return 0;
}
for (int i = 1; argv[i]; i++) {
const char *a = argv[i];
size_t len = strlen(a);
int need_quote = 0;
for (size_t j = 0; j < len; j++) {
if (_b_is_space(a[j]) || a[j] == '"') {
need_quote = 1;
break;
}
}
if (used && used + 1 < cap) {
buf[used++] = ' ';
}
if (need_quote && used + 1 < cap) {
buf[used++] = '"';
}
for (size_t j = 0; j < len; j++) {
if (a[j] == '"' && used + 2 < cap) {
buf[used++] = '\\';
}
if (used + 1 < cap) {
buf[used++] = a[j];
}
}
if (need_quote && used + 1 < cap) {
buf[used++] = '"';
}
if (used >= cap) {
errno = E2BIG;
return -1;
}
}
if (cap) {
buf[used < cap ? used : cap - 1] = '\0';
}
return 0;
}
static int _b_exec_common(const char *path, char *const argv[]) {
char resolved[260];
char args[512];
const char *exec_path = _b_resolve_exec_path(path, resolved, sizeof(resolved));
if (!exec_path) {
errno = ENOENT;
return -1;
}
if (_b_join_argv(args, sizeof(args), argv) != 0) {
return -1;
}
if (sys_exec(exec_path, args[0] ? args : NULL) < 0) {
errno = EIO;
return -1;
}
return 0;
}
__attribute__((weak)) int execv(const char *path, char *const argv[]) {
return _b_exec_common(path, argv);
}
__attribute__((weak)) int execve(const char *path, char *const argv[], char *const envp[]) {
(void)envp;
return _b_exec_common(path, argv);
}
__attribute__((weak)) int execvp(const char *file, char *const argv[]) {
return _b_exec_common(file, argv);
}
__attribute__((weak)) int execl(const char *path, const char *arg, ...) {
va_list ap;
char *argv[64];
int i = 0;
argv[i++] = (char *)arg;
va_start(ap, arg);
while (i < 63) {
char *v = va_arg(ap, char *);
argv[i++] = v;
if (!v) {
break;
}
}
va_end(ap);
if (argv[i - 1] != NULL) {
argv[63] = NULL;
}
return execv(path, argv);
}
__attribute__((weak)) int execlp(const char *file, const char *arg, ...) {
va_list ap;
char *argv[64];
int i = 0;
argv[i++] = (char *)arg;
va_start(ap, arg);
while (i < 63) {
char *v = va_arg(ap, char *);
argv[i++] = v;
if (!v) {
break;
}
}
va_end(ap);
if (argv[i - 1] != NULL) {
argv[63] = NULL;
}
return execvp(file, argv);
}
__attribute__((weak)) int execle(const char *path, const char *arg, ...) {
va_list ap;
char *argv[64];
int i = 0;
char *envp;
argv[i++] = (char *)arg;
va_start(ap, arg);
while (i < 63) {
char *v = va_arg(ap, char *);
argv[i++] = v;
if (!v) {
break;
}
}
envp = va_arg(ap, char *);
va_end(ap);
(void)envp;
if (argv[i - 1] != NULL) {
argv[63] = NULL;
}
return execv(path, argv);
}
__attribute__((weak)) pid_t waitpid(pid_t pid, int *status, int options) {
int st = 0;
for (;;) {
int rc = sys_waitpid((int)pid, &st, options);
if (rc > 0) {
if (status) {
*status = st;
}
return (pid_t)rc;
}
if (rc == 0 && (options & WNOHANG)) {
return 0;
}
if (rc < 0) {
errno = ECHILD;
return -1;
}
sys_yield();
}
}

View File

@@ -1,15 +1,108 @@
#include "signal.h"
#include "errno.h"
#include "stdlib.h"
#include "syscall.h"
static sighandler_t _signal_table[32] = {0};
typedef struct {
unsigned long sa_handler;
unsigned long sa_mask;
int sa_flags;
} k_sigaction_t;
__attribute__((weak)) sighandler_t signal(int sig, sighandler_t handler) {
sighandler_t old;
if (sig < 0 || sig >= (int)(sizeof(_signal_table) / sizeof(_signal_table[0]))) {
struct sigaction act;
struct sigaction old;
if (sig <= 0 || sig >= 32) {
errno = EINVAL;
return SIG_ERR;
}
old = _signal_table[sig];
_signal_table[sig] = handler;
return old;
act.sa_handler = handler;
act.sa_mask = 0;
act.sa_flags = 0;
if (sigaction(sig, &act, &old) != 0) {
return SIG_ERR;
}
return old.sa_handler;
}
__attribute__((weak)) int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
k_sigaction_t kact;
k_sigaction_t kold;
int rc;
if (sig <= 0 || sig >= 32) {
errno = EINVAL;
return -1;
}
if (act) {
kact.sa_handler = (unsigned long)act->sa_handler;
kact.sa_mask = (unsigned long)act->sa_mask;
kact.sa_flags = act->sa_flags;
}
rc = sys_sigaction(sig, act ? &kact : NULL, oldact ? &kold : NULL);
if (rc < 0) {
errno = EINVAL;
return -1;
}
if (oldact) {
oldact->sa_handler = (sighandler_t)kold.sa_handler;
oldact->sa_mask = (sigset_t)kold.sa_mask;
oldact->sa_flags = kold.sa_flags;
}
return 0;
}
__attribute__((weak)) int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
if (sys_sigprocmask(how,
(const unsigned long *)set,
(unsigned long *)oldset) < 0) {
errno = EINVAL;
return -1;
}
return 0;
}
__attribute__((weak)) int sigpending(sigset_t *set) {
if (!set) {
errno = EINVAL;
return -1;
}
if (sys_sigpending((unsigned long *)set) < 0) {
errno = EINVAL;
return -1;
}
return 0;
}
__attribute__((weak)) int raise(int sig) {
if (sig <= 0 || sig >= 32) {
errno = EINVAL;
return -1;
}
if (sys_kill_signal(-1, sig) < 0) {
errno = EINVAL;
return -1;
}
return 0;
}
__attribute__((weak)) int kill(pid_t pid, int sig) {
if (pid <= 0) {
errno = EINVAL;
return -1;
}
if (sys_kill_signal((int)pid, sig) < 0) {
errno = ENOTSUP;
return -1;
}
return 0;
}

View File

@@ -1,13 +1,37 @@
#ifndef BOREDOS_LIBC_SIGNAL_H
#define BOREDOS_LIBC_SIGNAL_H
#include "sys/types.h"
typedef void (*sighandler_t)(int);
typedef unsigned long sigset_t;
struct sigaction {
sighandler_t sa_handler;
sigset_t sa_mask;
int sa_flags;
};
#define SIG_DFL ((sighandler_t)0)
#define SIG_IGN ((sighandler_t)1)
#define SIG_ERR ((sighandler_t)-1)
#define SIGKILL 9
#define SIGTERM 15
#define SIGINT 2
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
sighandler_t signal(int sig, sighandler_t handler);
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigpending(sigset_t *set);
int raise(int sig);
int kill(pid_t pid, int sig);
#endif

View File

@@ -351,6 +351,13 @@ static void _b_append_strn(char *out, size_t cap, size_t *idx, const char *s, si
}
}
static void _b_append_repeat(char *out, size_t cap, size_t *idx, char ch, int count) {
int i;
for (i = 0; i < count; i++) {
_b_append_char(out, cap, idx, ch);
}
}
static void _b_utoa(unsigned long long v, unsigned base, int upper, char *buf, size_t *len) {
char tmp[64];
size_t i = 0;
@@ -420,6 +427,7 @@ static void _b_ftoa(double d, int precision, char *buf, size_t *len) {
__attribute__((weak)) int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
size_t out_i = 0;
while (*fmt) {
if (*fmt != '%') {
_b_append_char(str, size, &out_i, *fmt++);
@@ -433,26 +441,49 @@ __attribute__((weak)) int vsnprintf(char *str, size_t size, const char *fmt, va_
continue;
}
while (*fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '#' || *fmt == '0') {
fmt++;
}
{
int left = 0;
int plus = 0;
int space = 0;
int alt = 0;
int zero = 0;
int width = -1;
int precision = -1;
int lcount = 0;
char spec;
if (*fmt == '*') {
(void)va_arg(ap, int);
fmt++;
} else {
while (isdigit((unsigned char)*fmt)) {
while (*fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '#' || *fmt == '0') {
if (*fmt == '-') left = 1;
else if (*fmt == '+') plus = 1;
else if (*fmt == ' ') space = 1;
else if (*fmt == '#') alt = 1;
else if (*fmt == '0') zero = 1;
fmt++;
}
}
{
int precision = -1;
if (*fmt == '*') {
width = va_arg(ap, int);
if (width < 0) {
left = 1;
width = -width;
}
fmt++;
} else if (isdigit((unsigned char)*fmt)) {
width = 0;
while (isdigit((unsigned char)*fmt)) {
width = width * 10 + (*fmt - '0');
fmt++;
}
}
if (*fmt == '.') {
fmt++;
precision = 0;
if (*fmt == '*') {
precision = va_arg(ap, int);
if (precision < 0) {
precision = -1;
}
fmt++;
} else {
while (isdigit((unsigned char)*fmt)) {
@@ -462,57 +493,180 @@ __attribute__((weak)) int vsnprintf(char *str, size_t size, const char *fmt, va_
}
}
int lcount = 0;
while (*fmt == 'l') {
lcount++;
fmt++;
}
switch (*fmt) {
spec = *fmt;
if (!spec) {
break;
}
switch (spec) {
case 'd':
case 'i': {
long long v;
char nbuf[64];
size_t nlen = 0;
if (lcount >= 2) v = va_arg(ap, long long);
else if (lcount == 1) v = va_arg(ap, long);
else v = va_arg(ap, int);
_b_itoa(v, nbuf, &nlen);
_b_append_strn(str, size, &out_i, nbuf, nlen);
long long sv;
unsigned long long uv;
char digits[64];
size_t dlen = 0;
int neg = 0;
char signch = '\0';
int zeros = 0;
int spaces = 0;
int total;
if (lcount >= 2) sv = va_arg(ap, long long);
else if (lcount == 1) sv = va_arg(ap, long);
else sv = va_arg(ap, int);
if (sv < 0) {
neg = 1;
uv = (unsigned long long)(-(sv + 1)) + 1ULL;
} else {
uv = (unsigned long long)sv;
}
if (neg) signch = '-';
else if (plus) signch = '+';
else if (space) signch = ' ';
if (!(precision == 0 && uv == 0ULL)) {
_b_utoa(uv, 10U, 0, digits, &dlen);
}
if (precision > 0 && (size_t)precision > dlen) {
zeros = precision - (int)dlen;
}
if (precision < 0 && zero && !left && width > 0) {
int signw = (signch != '\0') ? 1 : 0;
int need = width - (signw + (int)dlen);
if (need > zeros) {
zeros = need;
}
}
total = ((signch != '\0') ? 1 : 0) + zeros + (int)dlen;
if (width > total) {
spaces = width - total;
}
if (!left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
if (signch != '\0') {
_b_append_char(str, size, &out_i, signch);
}
_b_append_repeat(str, size, &out_i, '0', zeros);
_b_append_strn(str, size, &out_i, digits, dlen);
if (left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
break;
}
case 'u':
case 'x':
case 'X':
case 'o': {
unsigned long long v;
unsigned base = (*fmt == 'o') ? 8U : ((*fmt == 'u') ? 10U : 16U);
char nbuf[64];
size_t nlen = 0;
int upper = (*fmt == 'X');
if (lcount >= 2) v = va_arg(ap, unsigned long long);
else if (lcount == 1) v = va_arg(ap, unsigned long);
else v = va_arg(ap, unsigned int);
_b_utoa(v, base, upper, nbuf, &nlen);
_b_append_strn(str, size, &out_i, nbuf, nlen);
unsigned long long uv;
unsigned base = (spec == 'o') ? 8U : ((spec == 'u') ? 10U : 16U);
int upper = (spec == 'X');
char digits[64];
size_t dlen = 0;
int zeros = 0;
int spaces = 0;
int prefix_len = 0;
char p1 = '\0';
char p2 = '\0';
int total;
if (lcount >= 2) uv = va_arg(ap, unsigned long long);
else if (lcount == 1) uv = va_arg(ap, unsigned long);
else uv = va_arg(ap, unsigned int);
if (!(precision == 0 && uv == 0ULL)) {
_b_utoa(uv, base, upper, digits, &dlen);
}
if (alt && uv != 0ULL) {
if (spec == 'x' || spec == 'X') {
p1 = '0';
p2 = upper ? 'X' : 'x';
prefix_len = 2;
} else if (spec == 'o') {
p1 = '0';
prefix_len = 1;
}
}
if (precision > 0 && (size_t)precision > dlen) {
zeros = precision - (int)dlen;
}
if (precision < 0 && zero && !left && width > 0) {
int need = width - (prefix_len + (int)dlen);
if (need > zeros) {
zeros = need;
}
}
total = prefix_len + zeros + (int)dlen;
if (width > total) {
spaces = width - total;
}
if (!left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
if (prefix_len >= 1) {
_b_append_char(str, size, &out_i, p1);
}
if (prefix_len >= 2) {
_b_append_char(str, size, &out_i, p2);
}
_b_append_repeat(str, size, &out_i, '0', zeros);
_b_append_strn(str, size, &out_i, digits, dlen);
if (left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
break;
}
case 'c': {
int c = va_arg(ap, int);
int spaces = (width > 1) ? (width - 1) : 0;
if (!left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
_b_append_char(str, size, &out_i, c);
if (left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
break;
}
case 's': {
const char *s = va_arg(ap, const char *);
size_t slen;
int spaces;
if (!s) s = "(null)";
slen = strlen(s);
if (precision >= 0 && (size_t)precision < slen) {
slen = (size_t)precision;
}
spaces = (width > (int)slen) ? (width - (int)slen) : 0;
if (!left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
_b_append_strn(str, size, &out_i, s, slen);
if (left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
break;
}
case 'p': {
uintptr_t v = (uintptr_t)va_arg(ap, void *);
char nbuf[32];
@@ -522,22 +676,33 @@ __attribute__((weak)) int vsnprintf(char *str, size_t size, const char *fmt, va_
_b_append_strn(str, size, &out_i, nbuf, nlen);
break;
}
case 'f':
case 'g':
case 'e': {
double v = va_arg(ap, double);
char nbuf[96];
size_t nlen = 0;
int spaces;
_b_ftoa(v, precision, nbuf, &nlen);
spaces = (width > (int)nlen) ? (width - (int)nlen) : 0;
if (!left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
_b_append_strn(str, size, &out_i, nbuf, nlen);
if (left) {
_b_append_repeat(str, size, &out_i, ' ', spaces);
}
break;
}
default:
_b_append_char(str, size, &out_i, '%');
_b_append_char(str, size, &out_i, *fmt);
_b_append_char(str, size, &out_i, spec);
break;
}
}
if (*fmt) {
fmt++;
}
@@ -547,6 +712,7 @@ __attribute__((weak)) int vsnprintf(char *str, size_t size, const char *fmt, va_
size_t term = (out_i < size - 1) ? out_i : (size - 1);
str[term] = '\0';
}
return (int)out_i;
}

View File

@@ -334,7 +334,7 @@ char* getcwd(char *buf, int size) {
}
void sleep(int ms) {
sys_system(46, ms, 0, 0, 0);
sys_system(SYSTEM_CMD_SLEEP, ms, 0, 0, 0);
}
void exit(int status) {

View File

@@ -1,11 +1,45 @@
#ifndef BOREDOS_LIBC_SYS_STAT_H
#define BOREDOS_LIBC_SYS_STAT_H
#include "types.h"
typedef long time_t;
struct stat {
unsigned long st_dev;
unsigned long st_ino;
mode_t st_mode;
unsigned long st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned long st_rdev;
int st_size;
int st_mode;
long st_blksize;
long st_blocks;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
#define S_IFMT 0170000
#define S_IFIFO 0010000
#define S_IFCHR 0020000
#define S_IFDIR 0040000
#define S_IFREG 0100000
#define S_IRUSR 0400
#define S_IWUSR 0200
#define S_IXUSR 0100
#define S_IRGRP 0040
#define S_IWGRP 0020
#define S_IXGRP 0010
#define S_IROTH 0004
#define S_IWOTH 0002
#define S_IXOTH 0001
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int mkdir(const char *pathname, int mode);

View File

@@ -4,5 +4,8 @@
typedef long ssize_t;
typedef long off_t;
typedef unsigned int mode_t;
typedef int pid_t;
typedef unsigned int uid_t;
typedef unsigned int gid_t;
#endif

View File

@@ -0,0 +1,15 @@
#ifndef BOREDOS_LIBC_SYS_WAIT_H
#define BOREDOS_LIBC_SYS_WAIT_H
#include "../sys/types.h"
#define WNOHANG 1
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#define WIFEXITED(status) ((((status) & 0x7f) == 0) ? 1 : 0)
#define WTERMSIG(status) ((status) & 0x7f)
#define WIFSIGNALED(status) (((status) & 0x7f) != 0)
pid_t waitpid(pid_t pid, int *status, int options);
#endif

View File

@@ -145,6 +145,22 @@ int sys_chdir(const char *path) {
return (int)syscall2(SYS_FS, FS_CMD_CHDIR, (uint64_t)path);
}
int sys_dup(int oldfd) {
return (int)syscall2(SYS_FS, FS_CMD_DUP, (uint64_t)oldfd);
}
int sys_dup2(int oldfd, int newfd) {
return (int)syscall3(SYS_FS, FS_CMD_DUP2, (uint64_t)oldfd, (uint64_t)newfd);
}
int sys_pipe(int pipefd[2]) {
return (int)syscall2(SYS_FS, FS_CMD_PIPE, (uint64_t)pipefd);
}
int sys_fcntl(int fd, int cmd, int val) {
return (int)syscall4(SYS_FS, FS_CMD_FCNTL, (uint64_t)fd, (uint64_t)cmd, (uint64_t)val);
}
int sys_tty_create(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_TTY_CREATE, 0);
}
@@ -165,6 +181,30 @@ int sys_spawn(const char *path, const char *args, uint64_t flags, uint64_t tty_i
return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_SPAWN, (uint64_t)path, (uint64_t)args, flags, (uint64_t)tty_id);
}
int sys_exec(const char *path, const char *args) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_EXEC, (uint64_t)path, (uint64_t)args, 0);
}
int sys_waitpid(int pid, int *status, int options) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_WAITPID, (uint64_t)pid, (uint64_t)status, (uint64_t)options);
}
int sys_kill_signal(int pid, int sig) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_KILL_SIGNAL, (uint64_t)pid, (uint64_t)sig, 0);
}
int sys_sigaction(int sig, const void *act, void *oldact) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_SIGACTION, (uint64_t)sig, (uint64_t)act, (uint64_t)oldact);
}
int sys_sigprocmask(int how, const unsigned long *set, unsigned long *oldset) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_SIGPROCMASK, (uint64_t)how, (uint64_t)set, (uint64_t)oldset);
}
int sys_sigpending(unsigned long *set) {
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_SIGPENDING, (uint64_t)set, 0);
}
int sys_tty_set_fg(int tty_id, int pid) {
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_TTY_SET_FG, (uint64_t)tty_id, (uint64_t)pid, 0);
}

View File

@@ -28,6 +28,10 @@
#define FS_CMD_GETCWD 12
#define FS_CMD_CHDIR 13
#define FS_CMD_GET_INFO 14
#define FS_CMD_DUP 15
#define FS_CMD_DUP2 16
#define FS_CMD_PIPE 17
#define FS_CMD_FCNTL 18
// System Commands (via SYS_SYSTEM)
#define SYSTEM_CMD_SET_BG_COLOR 1
@@ -44,6 +48,8 @@
#define SYSTEM_CMD_REBOOT 12
#define SYSTEM_CMD_SHUTDOWN 13
#define SYSTEM_CMD_BEEP 14
#define SYSTEM_CMD_GET_MEM_INFO 15
#define SYSTEM_CMD_GET_TICKS 16
#define SYSTEM_CMD_PCI_LIST 17
#define SYSTEM_CMD_NETWORK_DHCP 18
#define SYSTEM_CMD_NETWORK_GET_MAC 19
@@ -60,6 +66,7 @@
#define SYSTEM_CMD_NETWORK_GET_NIC_NAME 48
#define SYSTEM_CMD_SET_TEXT_COLOR 29
#define SYSTEM_CMD_SET_WALLPAPER_PATH 31
#define SYSTEM_CMD_RTC_SET 32
#define SYSTEM_CMD_TCP_CONNECT 33
#define SYSTEM_CMD_TCP_SEND 34
#define SYSTEM_CMD_TCP_RECV 35
@@ -67,10 +74,12 @@
#define SYSTEM_CMD_DNS_LOOKUP 37
#define SYSTEM_CMD_SET_DNS 38
#define SYSTEM_CMD_NET_UNLOCK 39
#define SYSTEM_CMD_SET_FONT 40
#define SYSTEM_CMD_SLEEP 46
#define SYSTEM_CMD_SET_RAW_MODE 41
#define SYSTEM_CMD_TCP_RECV_NB 42
#define SYSTEM_CMD_YIELD 43
#define SYSTEM_CMD_SET_RESOLUTION 47
#define SYSTEM_CMD_PARALLEL_RUN 50
#define SYSTEM_CMD_TTY_CREATE 60
#define SYSTEM_CMD_TTY_READ_OUT 61
@@ -82,10 +91,17 @@
#define SYSTEM_CMD_TTY_KILL_FG 67
#define SYSTEM_CMD_TTY_KILL_ALL 68
#define SYSTEM_CMD_TTY_DESTROY 69
#define SYSTEM_CMD_EXEC 70
#define SYSTEM_CMD_WAITPID 71
#define SYSTEM_CMD_KILL_SIGNAL 72
#define SYSTEM_CMD_SIGACTION 73
#define SYSTEM_CMD_SIGPROCMASK 74
#define SYSTEM_CMD_SIGPENDING 75
#define SPAWN_FLAG_TERMINAL 0x1
#define SPAWN_FLAG_INHERIT_TTY 0x2
#define SPAWN_FLAG_TTY_ID 0x4
#define SPAWN_FLAG_BACKGROUND 0x8
// Internal assembly entry into Ring 0
extern uint64_t syscall0(uint64_t sys_num);
@@ -128,12 +144,22 @@ int sys_mkdir(const char *path);
int sys_exists(const char *path);
int sys_getcwd(char *buf, int size);
int sys_chdir(const char *path);
int sys_dup(int oldfd);
int sys_dup2(int oldfd, int newfd);
int sys_pipe(int pipefd[2]);
int sys_fcntl(int fd, int cmd, int val);
int sys_tty_create(void);
int sys_tty_read_out(int tty_id, char *buf, int len);
int sys_tty_write_in(int tty_id, const char *buf, int len);
int sys_tty_read_in(char *buf, int len);
int sys_spawn(const char *path, const char *args, uint64_t flags, uint64_t tty_id);
int sys_exec(const char *path, const char *args);
int sys_waitpid(int pid, int *status, int options);
int sys_kill_signal(int pid, int sig);
int sys_sigaction(int sig, const void *act, void *oldact);
int sys_sigprocmask(int how, const unsigned long *set, unsigned long *oldset);
int sys_sigpending(unsigned long *set);
int sys_tty_set_fg(int tty_id, int pid);
int sys_tty_get_fg(int tty_id);
int sys_tty_kill_fg(int tty_id);

View File

@@ -1,6 +1,7 @@
#ifndef BOREDOS_LIBC_UNISTD_H
#define BOREDOS_LIBC_UNISTD_H
#include <stddef.h>
#include "sys/types.h"
#define SEEK_SET 0
@@ -18,5 +19,12 @@ ssize_t write(int fd, const void *buf, size_t count);
off_t lseek(int fd, off_t offset, int whence);
int unlink(const char *pathname);
int isatty(int fd);
int execv(const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...);
pid_t waitpid(pid_t pid, int *status, int options);
#endif