mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
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:
parent
ae8c7e21ac
commit
af5eda1647
35 changed files with 2234 additions and 208 deletions
|
|
@ -10,6 +10,7 @@
|
|||
#include "memory_manager.h"
|
||||
#include "elf.h"
|
||||
#include "wm.h"
|
||||
#include "vfs.h"
|
||||
#include "spinlock.h"
|
||||
#include "smp.h"
|
||||
#include "lapic.h"
|
||||
|
|
@ -29,6 +30,47 @@ static uint32_t next_cpu_assign = 1;
|
|||
|
||||
static void process_cleanup_inner(process_t *proc);
|
||||
|
||||
static void process_close_fd_inner(process_t *proc, int fd) {
|
||||
if (!proc || fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (ref) {
|
||||
ref->refs--;
|
||||
if (ref->refs <= 0) {
|
||||
if (ref->file) vfs_close((vfs_file_t *)ref->file);
|
||||
kfree(ref);
|
||||
}
|
||||
}
|
||||
} else if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ || proc->fd_kind[fd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
if (pipe) {
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ) pipe->readers--;
|
||||
else pipe->writers--;
|
||||
if (pipe->readers <= 0 && pipe->writers <= 0) {
|
||||
kfree(pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc->fds[fd] = NULL;
|
||||
proc->fd_kind[fd] = PROC_FD_KIND_NONE;
|
||||
proc->fd_flags[fd] = 0;
|
||||
}
|
||||
|
||||
static void process_init_signal_state(process_t *proc) {
|
||||
if (!proc) return;
|
||||
proc->signal_mask = 0;
|
||||
proc->signal_pending = 0;
|
||||
for (int i = 0; i < MAX_SIGNALS; i++) {
|
||||
proc->signal_handlers[i] = 0;
|
||||
proc->signal_action_mask[i] = 0;
|
||||
proc->signal_action_flags[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void process_init(void) {
|
||||
for (int i = 0; i < MAX_PROCESSES; i++) {
|
||||
processes[i].pid = 0xFFFFFFFF;
|
||||
|
|
@ -47,7 +89,16 @@ void process_init(void) {
|
|||
|
||||
kernel_proc->fpu_initialized = true;
|
||||
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) kernel_proc->fds[i] = NULL;
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||
kernel_proc->fds[i] = NULL;
|
||||
kernel_proc->fd_kind[i] = 0;
|
||||
kernel_proc->fd_flags[i] = 0;
|
||||
}
|
||||
kernel_proc->parent_pid = 0;
|
||||
kernel_proc->pgid = 0;
|
||||
kernel_proc->exited = false;
|
||||
kernel_proc->exit_status = 0;
|
||||
process_init_signal_state(kernel_proc);
|
||||
|
||||
extern void mem_memcpy(void *dest, const void *src, size_t len);
|
||||
mem_memcpy(kernel_proc->name, "kernel", 7);
|
||||
|
|
@ -77,12 +128,18 @@ process_t* process_create(void (*entry_point)(void), bool is_user) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
process_t *parent = process_get_current();
|
||||
|
||||
new_proc->pid = next_pid++;
|
||||
new_proc->is_user = is_user;
|
||||
new_proc->tty_id = -1;
|
||||
new_proc->kill_pending = false;
|
||||
new_proc->parent_pid = parent ? parent->pid : 0;
|
||||
new_proc->pgid = parent ? parent->pgid : new_proc->pid;
|
||||
new_proc->exited = false;
|
||||
new_proc->exit_status = 0;
|
||||
process_init_signal_state(new_proc);
|
||||
|
||||
process_t *parent = process_get_current();
|
||||
if (parent) {
|
||||
extern void mem_memcpy(void *dest, const void *src, size_t len);
|
||||
mem_memcpy(new_proc->cwd, parent->cwd, 1024);
|
||||
|
|
@ -204,7 +261,11 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t
|
|||
new_proc->pml4_phys = paging_create_user_pml4_phys();
|
||||
if (!new_proc->pml4_phys) return NULL;
|
||||
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) new_proc->fds[i] = NULL;
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||
new_proc->fds[i] = NULL;
|
||||
new_proc->fd_kind[i] = 0;
|
||||
new_proc->fd_flags[i] = 0;
|
||||
}
|
||||
new_proc->gui_event_head = 0;
|
||||
new_proc->gui_event_tail = 0;
|
||||
new_proc->ui_window = NULL;
|
||||
|
|
@ -213,15 +274,22 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t
|
|||
new_proc->is_terminal_proc = terminal_proc;
|
||||
new_proc->tty_id = tty_id;
|
||||
new_proc->kill_pending = false;
|
||||
new_proc->exited = false;
|
||||
new_proc->exit_status = 0;
|
||||
process_init_signal_state(new_proc);
|
||||
|
||||
process_t *parent = process_get_current();
|
||||
if (parent) {
|
||||
extern void mem_memcpy(void *dest, const void *src, size_t len);
|
||||
mem_memcpy(new_proc->cwd, parent->cwd, 1024);
|
||||
new_proc->parent_pid = parent->pid;
|
||||
new_proc->pgid = parent->pgid;
|
||||
} else {
|
||||
extern void mem_memset(void *dest, int val, size_t len);
|
||||
mem_memset(new_proc->cwd, 0, 1024);
|
||||
new_proc->cwd[0] = '/';
|
||||
new_proc->parent_pid = 0;
|
||||
new_proc->pgid = new_proc->pid;
|
||||
}
|
||||
|
||||
// 2. Load ELF executable
|
||||
|
|
@ -469,7 +537,7 @@ uint64_t process_schedule(uint64_t current_rsp) {
|
|||
|
||||
current_process[my_cpu] = next_proc;
|
||||
|
||||
cur->pid = 0xFFFFFFFF;
|
||||
cur->exited = true;
|
||||
cur->cpu_affinity = 0xFFFFFFFF;
|
||||
cur->ui_window = NULL;
|
||||
cur->is_terminal_proc = false;
|
||||
|
|
@ -570,7 +638,7 @@ uint64_t process_schedule(uint64_t current_rsp) {
|
|||
|
||||
process_t* process_get_by_pid(uint32_t pid) {
|
||||
for (int i = 0; i < MAX_PROCESSES; i++) {
|
||||
if (processes[i].pid == pid) return &processes[i];
|
||||
if (processes[i].pid == pid && !processes[i].exited) return &processes[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -593,12 +661,8 @@ static void process_cleanup_inner(process_t *proc) {
|
|||
proc->ui_window = NULL;
|
||||
}
|
||||
|
||||
extern void fat32_close(struct FAT32_FileHandle *fh);
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||
if (proc->fds[i]) {
|
||||
fat32_close(proc->fds[i]);
|
||||
proc->fds[i] = NULL;
|
||||
}
|
||||
process_close_fd_inner(proc, i);
|
||||
}
|
||||
|
||||
extern void cmd_process_finished(void);
|
||||
|
|
@ -613,12 +677,18 @@ static void process_cleanup_inner(process_t *proc) {
|
|||
}
|
||||
|
||||
void process_terminate(process_t *to_delete) {
|
||||
process_terminate_with_status(to_delete, 0);
|
||||
}
|
||||
|
||||
void process_terminate_with_status(process_t *to_delete, int status) {
|
||||
if (!to_delete || to_delete->pid == 0xFFFFFFFF || to_delete->pid == 0) return;
|
||||
|
||||
uint32_t cpu_count = smp_cpu_count();
|
||||
for (uint32_t c = 0; c < cpu_count && c < MAX_CPUS_SCHED; c++) {
|
||||
if (current_process[c] == to_delete) {
|
||||
to_delete->kill_pending = true;
|
||||
to_delete->exit_status = status;
|
||||
to_delete->exited = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -662,13 +732,13 @@ void process_terminate(process_t *to_delete) {
|
|||
}
|
||||
|
||||
// Mark slot as free
|
||||
to_delete->pid = 0xFFFFFFFF;
|
||||
to_delete->cpu_affinity = 0xFFFFFFFF;
|
||||
to_delete->kill_pending = false;
|
||||
to_delete->exited = true;
|
||||
to_delete->exit_status = status;
|
||||
|
||||
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
|
||||
// Defer kernel stack until we switch away from it
|
||||
to_delete->kernel_stack_alloc = NULL;
|
||||
if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc);
|
||||
|
||||
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
|
||||
if (to_delete->pml4_phys && to_delete->is_user) {
|
||||
|
|
@ -694,6 +764,8 @@ uint64_t process_terminate_current(void) {
|
|||
}
|
||||
|
||||
process_cleanup_inner(cur);
|
||||
cur->exited = true;
|
||||
cur->exit_status = 0;
|
||||
|
||||
// 2. Find previous process in circular list
|
||||
process_t *prev = cur;
|
||||
|
|
@ -729,7 +801,6 @@ uint64_t process_terminate_current(void) {
|
|||
current_process[my_cpu] = next_proc;
|
||||
|
||||
// Mark slot as free
|
||||
to_delete->pid = 0xFFFFFFFF;
|
||||
to_delete->cpu_affinity = 0xFFFFFFFF;
|
||||
to_delete->ui_window = NULL;
|
||||
to_delete->is_terminal_proc = false;
|
||||
|
|
@ -756,6 +827,222 @@ uint64_t process_terminate_current(void) {
|
|||
return next_rsp;
|
||||
}
|
||||
|
||||
int process_reap(uint32_t caller_pid, uint32_t pid, int *status_out) {
|
||||
process_t *p = NULL;
|
||||
for (int i = 0; i < MAX_PROCESSES; i++) {
|
||||
if (processes[i].pid == pid) {
|
||||
p = &processes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p) return -1;
|
||||
if (!p->exited) return -2;
|
||||
if (p->parent_pid != caller_pid && caller_pid != 0) return -1;
|
||||
|
||||
if (status_out) {
|
||||
*status_out = p->exit_status;
|
||||
}
|
||||
|
||||
p->pid = 0xFFFFFFFF;
|
||||
p->parent_pid = 0;
|
||||
p->pgid = 0;
|
||||
p->cpu_affinity = 0xFFFFFFFF;
|
||||
p->exited = false;
|
||||
p->exit_status = 0;
|
||||
p->sleep_until = 0;
|
||||
p->ui_window = NULL;
|
||||
p->is_terminal_proc = false;
|
||||
p->tty_id = -1;
|
||||
p->kill_pending = false;
|
||||
p->used_memory = 0;
|
||||
p->ticks = 0;
|
||||
p->next = NULL;
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||
p->fds[i] = NULL;
|
||||
p->fd_kind[i] = PROC_FD_KIND_NONE;
|
||||
p->fd_flags[i] = 0;
|
||||
}
|
||||
process_init_signal_state(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_waitpid(uint32_t caller_pid, int target_pid, int options, int *status_out) {
|
||||
process_t *caller = process_get_by_pid(caller_pid);
|
||||
int found_child = 0;
|
||||
int found_waitable = 0;
|
||||
|
||||
for (int i = 0; i < MAX_PROCESSES; i++) {
|
||||
process_t *p = &processes[i];
|
||||
int match = 0;
|
||||
|
||||
if (p->pid == 0xFFFFFFFF || p->pid == 0 || p->parent_pid != caller_pid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
found_child = 1;
|
||||
if (target_pid > 0) {
|
||||
match = ((int)p->pid == target_pid);
|
||||
} else if (target_pid == -1) {
|
||||
match = 1;
|
||||
} else if (target_pid == 0) {
|
||||
match = (caller && p->pgid == caller->pgid);
|
||||
} else {
|
||||
match = (p->pgid == (uint32_t)(-target_pid));
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
found_waitable = 1;
|
||||
if (!p->exited) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (process_reap(caller_pid, p->pid, status_out) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return (int)p->pid;
|
||||
}
|
||||
|
||||
if (!found_child || !found_waitable) {
|
||||
return -1;
|
||||
}
|
||||
if (options & 1) {
|
||||
return 0;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int process_exec_replace_current(registers_t *regs, const char* filepath, const char* args_str) {
|
||||
process_t *proc = process_get_current();
|
||||
if (!proc || !proc->is_user || !regs || !filepath) return -1;
|
||||
|
||||
uint64_t new_pml4 = paging_create_user_pml4_phys();
|
||||
if (!new_pml4) return -1;
|
||||
|
||||
size_t elf_load_size = 0;
|
||||
uint64_t entry_point = elf_load(filepath, new_pml4, &elf_load_size);
|
||||
if (entry_point == 0) {
|
||||
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
|
||||
paging_destroy_user_pml4_phys(new_pml4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t user_stack_size = 262144;
|
||||
void* stack = kmalloc_aligned(user_stack_size, 4096);
|
||||
if (!stack) {
|
||||
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
|
||||
paging_destroy_user_pml4_phys(new_pml4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < (user_stack_size / 4096); i++) {
|
||||
paging_map_page(new_pml4, 0x800000 - user_stack_size + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER);
|
||||
}
|
||||
|
||||
int argc = 1;
|
||||
char *args_buf = (char *)stack + user_stack_size;
|
||||
uint64_t user_args_buf = 0x800000;
|
||||
|
||||
int path_len = 0;
|
||||
while (filepath[path_len]) path_len++;
|
||||
args_buf -= (path_len + 1);
|
||||
user_args_buf -= (path_len + 1);
|
||||
for (int i = 0; i <= path_len; i++) args_buf[i] = filepath[i];
|
||||
|
||||
uint64_t argv_ptrs[32];
|
||||
argv_ptrs[0] = user_args_buf;
|
||||
|
||||
if (args_str) {
|
||||
int i = 0;
|
||||
while (args_str[i] && argc < 31) {
|
||||
while (args_str[i] == ' ') i++;
|
||||
if (!args_str[i]) break;
|
||||
|
||||
int arg_start = i;
|
||||
bool in_quotes = false;
|
||||
if (args_str[i] == '"') {
|
||||
in_quotes = true;
|
||||
i++;
|
||||
arg_start = i;
|
||||
while (args_str[i] && args_str[i] != '"') i++;
|
||||
} else {
|
||||
while (args_str[i] && args_str[i] != ' ') i++;
|
||||
}
|
||||
|
||||
int arg_len = i - arg_start;
|
||||
args_buf -= (arg_len + 1);
|
||||
user_args_buf -= (arg_len + 1);
|
||||
for (int k = 0; k < arg_len; k++) args_buf[k] = args_str[arg_start + k];
|
||||
args_buf[arg_len] = '\0';
|
||||
argv_ptrs[argc++] = user_args_buf;
|
||||
if (in_quotes && args_str[i] == '"') i++;
|
||||
}
|
||||
}
|
||||
argv_ptrs[argc] = 0;
|
||||
|
||||
uint64_t current_user_sp = user_args_buf;
|
||||
current_user_sp &= ~7ULL;
|
||||
args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - user_stack_size)));
|
||||
|
||||
int argv_size = (argc + 1) * (int)sizeof(uint64_t);
|
||||
args_buf -= argv_size;
|
||||
current_user_sp -= argv_size;
|
||||
uint64_t actual_argv_ptr = current_user_sp;
|
||||
uint64_t *user_argv_array = (uint64_t *)args_buf;
|
||||
for (int i = 0; i <= argc; i++) user_argv_array[i] = argv_ptrs[i];
|
||||
|
||||
current_user_sp &= ~15ULL;
|
||||
|
||||
if (proc->user_stack_alloc) {
|
||||
kfree(proc->user_stack_alloc);
|
||||
}
|
||||
if (proc->pml4_phys) {
|
||||
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
|
||||
paging_destroy_user_pml4_phys(proc->pml4_phys);
|
||||
}
|
||||
|
||||
proc->pml4_phys = new_pml4;
|
||||
proc->user_stack_alloc = stack;
|
||||
proc->used_memory = elf_load_size + user_stack_size + 65536;
|
||||
proc->heap_start = 0x20000000;
|
||||
proc->heap_end = 0x20000000;
|
||||
proc->sleep_until = 0;
|
||||
process_init_signal_state(proc);
|
||||
|
||||
int last_slash = -1;
|
||||
for (int i = 0; filepath[i]; i++) if (filepath[i] == '/') last_slash = i;
|
||||
const char *filename = (last_slash == -1) ? filepath : (filepath + last_slash + 1);
|
||||
int ni = 0;
|
||||
while (filename[ni] && ni < 63) {
|
||||
proc->name[ni] = filename[ni];
|
||||
ni++;
|
||||
}
|
||||
proc->name[ni] = 0;
|
||||
|
||||
regs->rip = entry_point;
|
||||
regs->rdi = argc;
|
||||
regs->rsi = actual_argv_ptr;
|
||||
regs->rsp = current_user_sp;
|
||||
regs->rax = 0;
|
||||
regs->rbx = 0;
|
||||
regs->rcx = 0;
|
||||
regs->rdx = 0;
|
||||
regs->r8 = 0;
|
||||
regs->r9 = 0;
|
||||
regs->r10 = 0;
|
||||
regs->r11 = 0;
|
||||
regs->r12 = 0;
|
||||
regs->r13 = 0;
|
||||
regs->r14 = 0;
|
||||
regs->r15 = 0;
|
||||
regs->rbp = 0;
|
||||
|
||||
paging_switch_directory(proc->pml4_phys);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// SMP: IPI handler called on AP cores when BSP broadcasts scheduling IPI
|
||||
uint64_t sched_ipi_handler(registers_t *regs) {
|
||||
lapic_eoi(); // Acknowledge the IPI
|
||||
|
|
|
|||
|
|
@ -11,6 +11,26 @@
|
|||
|
||||
#define MAX_GUI_EVENTS 32
|
||||
#define MAX_PROCESS_FDS 16
|
||||
#define MAX_SIGNALS 32
|
||||
|
||||
#define PROC_FD_KIND_NONE 0
|
||||
#define PROC_FD_KIND_FILE 1
|
||||
#define PROC_FD_KIND_PIPE_READ 2
|
||||
#define PROC_FD_KIND_PIPE_WRITE 3
|
||||
|
||||
typedef struct {
|
||||
void *file;
|
||||
int refs;
|
||||
} process_fd_file_ref_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[4096];
|
||||
uint32_t read_pos;
|
||||
uint32_t write_pos;
|
||||
uint32_t count;
|
||||
int readers;
|
||||
int writers;
|
||||
} process_fd_pipe_t;
|
||||
|
||||
struct FAT32_FileHandle;
|
||||
|
||||
|
|
@ -38,6 +58,8 @@ typedef struct process {
|
|||
uint64_t heap_end;
|
||||
|
||||
void *fds[MAX_PROCESS_FDS];
|
||||
uint8_t fd_kind[MAX_PROCESS_FDS];
|
||||
int fd_flags[MAX_PROCESS_FDS];
|
||||
|
||||
void *kernel_stack_alloc;
|
||||
void *user_stack_alloc;
|
||||
|
|
@ -57,6 +79,17 @@ typedef struct process {
|
|||
uint32_t cpu_affinity;
|
||||
bool is_idle;
|
||||
char cwd[1024];
|
||||
|
||||
uint32_t parent_pid;
|
||||
uint32_t pgid;
|
||||
bool exited;
|
||||
int exit_status;
|
||||
|
||||
uint64_t signal_mask;
|
||||
uint64_t signal_pending;
|
||||
uint64_t signal_handlers[MAX_SIGNALS];
|
||||
uint64_t signal_action_mask[MAX_SIGNALS];
|
||||
int signal_action_flags[MAX_SIGNALS];
|
||||
} __attribute__((aligned(16))) process_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -70,13 +103,17 @@ typedef struct {
|
|||
void process_init(void);
|
||||
process_t* process_create(void (*entry_point)(void), bool is_user);
|
||||
process_t* process_create_elf(const char* filepath, const char* args_str, bool terminal_proc, int tty_id);
|
||||
int process_exec_replace_current(registers_t *regs, const char* filepath, const char* args_str);
|
||||
process_t* process_get_current(void);
|
||||
void process_set_current_for_cpu(uint32_t cpu_id, process_t* p);
|
||||
process_t* process_get_current_for_cpu(uint32_t cpu_id);
|
||||
uint64_t process_schedule(uint64_t current_rsp);
|
||||
uint64_t process_terminate_current(void);
|
||||
void process_terminate(process_t *proc);
|
||||
void process_terminate_with_status(process_t *proc, int status);
|
||||
process_t* process_get_by_pid(uint32_t pid);
|
||||
int process_waitpid(uint32_t caller_pid, int target_pid, int options, int *status_out);
|
||||
int process_reap(uint32_t caller_pid, uint32_t pid, int *status_out);
|
||||
void process_kill_by_tty(int tty_id);
|
||||
|
||||
// SMP: IPI handler for AP scheduling
|
||||
|
|
|
|||
|
|
@ -967,6 +967,35 @@ static const syscall_handler_fn gui_cmd_table[GUI_CMD_TABLE_SIZE] = {
|
|||
[GUI_CMD_GET_DATETIME] = gui_cmd_get_datetime,
|
||||
};
|
||||
|
||||
#define O_RDONLY 0x0000
|
||||
#define O_WRONLY 0x0001
|
||||
#define O_RDWR 0x0002
|
||||
#define O_APPEND 0x0400
|
||||
#define O_NONBLOCK 0x0800
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
|
||||
static int fs_alloc_fd_slot(process_t *proc, int start) {
|
||||
for (int i = start; i < MAX_PROCESS_FDS; i++) {
|
||||
if (!proc->fds[i]) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int fs_mode_to_flags(const char *mode) {
|
||||
if (!mode || !mode[0]) return O_RDONLY;
|
||||
if (mode[0] == 'r') {
|
||||
return (mode[1] == '+') ? O_RDWR : O_RDONLY;
|
||||
}
|
||||
if (mode[0] == 'a') {
|
||||
return (mode[1] == '+') ? (O_RDWR | O_APPEND) : (O_WRONLY | O_APPEND);
|
||||
}
|
||||
if (mode[0] == 'w') {
|
||||
return (mode[1] == '+') ? O_RDWR : O_WRONLY;
|
||||
}
|
||||
return O_RDONLY;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_open(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
const char *path = (const char *)args->arg2;
|
||||
|
|
@ -977,13 +1006,25 @@ static uint64_t fs_cmd_open(const syscall_args_t *args) {
|
|||
// but let's be explicit if we can.
|
||||
vfs_file_t *vf = vfs_open(path, mode);
|
||||
if (!vf) return -1;
|
||||
|
||||
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)kmalloc(sizeof(process_fd_file_ref_t));
|
||||
if (!ref) {
|
||||
vfs_close(vf);
|
||||
return -1;
|
||||
}
|
||||
ref->file = vf;
|
||||
ref->refs = 1;
|
||||
|
||||
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
|
||||
if (proc->fds[i] == NULL) {
|
||||
proc->fds[i] = vf;
|
||||
proc->fds[i] = ref;
|
||||
proc->fd_kind[i] = PROC_FD_KIND_FILE;
|
||||
proc->fd_flags[i] = fs_mode_to_flags(mode);
|
||||
return (uint64_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(ref);
|
||||
vfs_close(vf);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -994,7 +1035,35 @@ static uint64_t fs_cmd_read(const syscall_args_t *args) {
|
|||
void *buf = (void *)args->arg3;
|
||||
uint32_t len = (uint32_t)args->arg4;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
return (uint64_t)vfs_read((vfs_file_t*)proc->fds[fd], buf, (int)len);
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (!ref || !ref->file) return -1;
|
||||
return (uint64_t)vfs_read(ref->file, buf, (int)len);
|
||||
}
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
if (!pipe || !buf) return -1;
|
||||
uint8_t *out = (uint8_t *)buf;
|
||||
uint32_t n = 0;
|
||||
while (n < len) {
|
||||
if (pipe->count == 0) {
|
||||
if (pipe->writers == 0) break;
|
||||
if (proc->fd_flags[fd] & O_NONBLOCK) {
|
||||
if (n == 0) return (uint64_t)-1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
out[n++] = pipe->data[pipe->read_pos];
|
||||
pipe->read_pos = (pipe->read_pos + 1) % sizeof(pipe->data);
|
||||
pipe->count--;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_write(const syscall_args_t *args) {
|
||||
|
|
@ -1003,15 +1072,65 @@ static uint64_t fs_cmd_write(const syscall_args_t *args) {
|
|||
const void *buf = (const void *)args->arg3;
|
||||
uint32_t len = (uint32_t)args->arg4;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
return (uint64_t)vfs_write((vfs_file_t*)proc->fds[fd], buf, (int)len);
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (!ref || !ref->file) return -1;
|
||||
return (uint64_t)vfs_write(ref->file, buf, (int)len);
|
||||
}
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
if (!pipe || !buf) return -1;
|
||||
if (pipe->readers <= 0) return (uint64_t)-1;
|
||||
const uint8_t *in = (const uint8_t *)buf;
|
||||
uint32_t n = 0;
|
||||
while (n < len) {
|
||||
if (pipe->count == sizeof(pipe->data)) {
|
||||
if (proc->fd_flags[fd] & O_NONBLOCK) {
|
||||
if (n == 0) return (uint64_t)-1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pipe->data[pipe->write_pos] = in[n++];
|
||||
pipe->write_pos = (pipe->write_pos + 1) % sizeof(pipe->data);
|
||||
pipe->count++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_close(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int fd = (int)args->arg2;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
vfs_close((vfs_file_t*)proc->fds[fd]);
|
||||
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (ref) {
|
||||
ref->refs--;
|
||||
if (ref->refs <= 0) {
|
||||
if (ref->file) vfs_close(ref->file);
|
||||
kfree(ref);
|
||||
}
|
||||
}
|
||||
} else if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ || proc->fd_kind[fd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
if (pipe) {
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ) pipe->readers--;
|
||||
else pipe->writers--;
|
||||
if (pipe->readers <= 0 && pipe->writers <= 0) {
|
||||
kfree(pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc->fds[fd] = NULL;
|
||||
proc->fd_kind[fd] = PROC_FD_KIND_NONE;
|
||||
proc->fd_flags[fd] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1021,21 +1140,142 @@ static uint64_t fs_cmd_seek(const syscall_args_t *args) {
|
|||
int offset = (int)args->arg3;
|
||||
int whence = (int)args->arg4; // 0=SET, 1=CUR, 2=END
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
return (uint64_t)vfs_seek((vfs_file_t*)proc->fds[fd], offset, whence);
|
||||
if (proc->fd_kind[fd] != PROC_FD_KIND_FILE) return -1;
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (!ref || !ref->file) return -1;
|
||||
return (uint64_t)vfs_seek(ref->file, offset, whence);
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_tell(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int fd = (int)args->arg2;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
return (uint64_t)vfs_file_position((vfs_file_t*)proc->fds[fd]);
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ || proc->fd_kind[fd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
return pipe ? pipe->count : 0;
|
||||
}
|
||||
if (proc->fd_kind[fd] != PROC_FD_KIND_FILE) return -1;
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (!ref || !ref->file) return -1;
|
||||
return (uint64_t)vfs_file_position(ref->file);
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_size(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int fd = (int)args->arg2;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
return (uint64_t)vfs_file_size((vfs_file_t*)proc->fds[fd]);
|
||||
if (proc->fd_kind[fd] == PROC_FD_KIND_PIPE_READ || proc->fd_kind[fd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[fd];
|
||||
return pipe ? pipe->count : 0;
|
||||
}
|
||||
if (proc->fd_kind[fd] != PROC_FD_KIND_FILE) return -1;
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[fd];
|
||||
if (!ref || !ref->file) return -1;
|
||||
return (uint64_t)vfs_file_size(ref->file);
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_dup(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int oldfd = (int)args->arg2;
|
||||
if (oldfd < 0 || oldfd >= MAX_PROCESS_FDS || !proc->fds[oldfd]) return -1;
|
||||
|
||||
int newfd = fs_alloc_fd_slot(proc, 0);
|
||||
if (newfd < 0) return -1;
|
||||
|
||||
proc->fds[newfd] = proc->fds[oldfd];
|
||||
proc->fd_kind[newfd] = proc->fd_kind[oldfd];
|
||||
proc->fd_flags[newfd] = proc->fd_flags[oldfd];
|
||||
|
||||
if (proc->fd_kind[oldfd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[oldfd];
|
||||
if (ref) ref->refs++;
|
||||
} else if (proc->fd_kind[oldfd] == PROC_FD_KIND_PIPE_READ) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[oldfd];
|
||||
if (pipe) pipe->readers++;
|
||||
} else if (proc->fd_kind[oldfd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[oldfd];
|
||||
if (pipe) pipe->writers++;
|
||||
}
|
||||
|
||||
return (uint64_t)newfd;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_dup2(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int oldfd = (int)args->arg2;
|
||||
int newfd = (int)args->arg3;
|
||||
if (oldfd < 0 || oldfd >= MAX_PROCESS_FDS || !proc->fds[oldfd]) return -1;
|
||||
if (newfd < 0 || newfd >= MAX_PROCESS_FDS) return -1;
|
||||
if (oldfd == newfd) return (uint64_t)newfd;
|
||||
|
||||
if (proc->fds[newfd]) {
|
||||
syscall_args_t close_args = *args;
|
||||
close_args.arg2 = (uint64_t)newfd;
|
||||
if (fs_cmd_close(&close_args) != 0) return -1;
|
||||
}
|
||||
|
||||
proc->fds[newfd] = proc->fds[oldfd];
|
||||
proc->fd_kind[newfd] = proc->fd_kind[oldfd];
|
||||
proc->fd_flags[newfd] = proc->fd_flags[oldfd];
|
||||
|
||||
if (proc->fd_kind[oldfd] == PROC_FD_KIND_FILE) {
|
||||
process_fd_file_ref_t *ref = (process_fd_file_ref_t *)proc->fds[oldfd];
|
||||
if (ref) ref->refs++;
|
||||
} else if (proc->fd_kind[oldfd] == PROC_FD_KIND_PIPE_READ) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[oldfd];
|
||||
if (pipe) pipe->readers++;
|
||||
} else if (proc->fd_kind[oldfd] == PROC_FD_KIND_PIPE_WRITE) {
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)proc->fds[oldfd];
|
||||
if (pipe) pipe->writers++;
|
||||
}
|
||||
|
||||
return (uint64_t)newfd;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_pipe(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int *pipefd = (int *)args->arg2;
|
||||
if (!pipefd) return -1;
|
||||
|
||||
int rfd = fs_alloc_fd_slot(proc, 0);
|
||||
if (rfd < 0) return -1;
|
||||
int wfd = fs_alloc_fd_slot(proc, rfd + 1);
|
||||
if (wfd < 0) return -1;
|
||||
|
||||
process_fd_pipe_t *pipe = (process_fd_pipe_t *)kmalloc(sizeof(process_fd_pipe_t));
|
||||
if (!pipe) return -1;
|
||||
mem_memset(pipe, 0, sizeof(*pipe));
|
||||
pipe->readers = 1;
|
||||
pipe->writers = 1;
|
||||
|
||||
proc->fds[rfd] = pipe;
|
||||
proc->fd_kind[rfd] = PROC_FD_KIND_PIPE_READ;
|
||||
proc->fd_flags[rfd] = O_RDONLY;
|
||||
|
||||
proc->fds[wfd] = pipe;
|
||||
proc->fd_kind[wfd] = PROC_FD_KIND_PIPE_WRITE;
|
||||
proc->fd_flags[wfd] = O_WRONLY;
|
||||
|
||||
pipefd[0] = rfd;
|
||||
pipefd[1] = wfd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_fcntl(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int fd = (int)args->arg2;
|
||||
int cmd = (int)args->arg3;
|
||||
int val = (int)args->arg4;
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
|
||||
|
||||
if (cmd == F_GETFL) {
|
||||
return (uint64_t)proc->fd_flags[fd];
|
||||
}
|
||||
if (cmd == F_SETFL) {
|
||||
proc->fd_flags[fd] = (proc->fd_flags[fd] & ~(O_APPEND | O_NONBLOCK)) | (val & (O_APPEND | O_NONBLOCK));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint64_t fs_cmd_list(const syscall_args_t *args) {
|
||||
|
|
@ -1137,7 +1377,7 @@ static uint64_t fs_cmd_chdir(const syscall_args_t *args) {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
#define FS_CMD_TABLE_SIZE 15
|
||||
#define FS_CMD_TABLE_SIZE 19
|
||||
static const syscall_handler_fn fs_cmd_table[FS_CMD_TABLE_SIZE] = {
|
||||
[FS_CMD_OPEN] = fs_cmd_open, // 1
|
||||
[FS_CMD_READ] = fs_cmd_read, // 2
|
||||
|
|
@ -1153,6 +1393,10 @@ static const syscall_handler_fn fs_cmd_table[FS_CMD_TABLE_SIZE] = {
|
|||
[FS_CMD_GETCWD] = fs_cmd_getcwd, // 12
|
||||
[FS_CMD_CHDIR] = fs_cmd_chdir, // 13
|
||||
[FS_CMD_GET_INFO] = fs_cmd_get_info, // 14
|
||||
[FS_CMD_DUP] = fs_cmd_dup, // 15
|
||||
[FS_CMD_DUP2] = fs_cmd_dup2, // 16
|
||||
[FS_CMD_PIPE] = fs_cmd_pipe, // 17
|
||||
[FS_CMD_FCNTL] = fs_cmd_fcntl, // 18
|
||||
};
|
||||
|
||||
static uint64_t sys_cmd_set_bg_color(const syscall_args_t *args) {
|
||||
|
|
@ -1178,7 +1422,7 @@ static uint64_t sys_cmd_set_bg_pattern(const syscall_args_t *args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_set_wallpaper_obsolete(const syscall_args_t *args) {
|
||||
static uint64_t sys_cmd_set_wallpaper(const syscall_args_t *args) {
|
||||
(void)args;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1230,7 +1474,7 @@ static uint64_t sys_cmd_get_mouse_speed(const syscall_args_t *args) {
|
|||
return mouse_speed;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_get_wallpaper_thumb_obsolete(const syscall_args_t *args) {
|
||||
static uint64_t sys_cmd_get_wallpaper_thumb(const syscall_args_t *args) {
|
||||
(void)args;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1270,6 +1514,21 @@ static uint64_t sys_cmd_beep(const syscall_args_t *args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_get_mem_info(const syscall_args_t *args) {
|
||||
uint64_t *out = (uint64_t *)args->arg2;
|
||||
if (!out) return -1;
|
||||
MemStats stats = memory_get_stats();
|
||||
out[0] = (uint64_t)stats.total_memory;
|
||||
out[1] = (uint64_t)stats.used_memory;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_get_ticks(const syscall_args_t *args) {
|
||||
(void)args;
|
||||
extern uint32_t wm_get_ticks(void);
|
||||
return (uint64_t)wm_get_ticks();
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_pci_list(const syscall_args_t *args) {
|
||||
typedef struct {
|
||||
uint16_t vendor;
|
||||
|
|
@ -1661,6 +1920,140 @@ static uint64_t sys_cmd_spawn_process(const syscall_args_t *args) {
|
|||
return (uint64_t)child->pid;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint64_t sa_handler;
|
||||
uint64_t sa_mask;
|
||||
int sa_flags;
|
||||
} k_sigaction_t;
|
||||
|
||||
#define SA_RESETHAND 0x80000000
|
||||
#define SIGKILL_NUM 9
|
||||
|
||||
static uint64_t sys_cmd_exec_process(const syscall_args_t *args) {
|
||||
const char *user_path = (const char *)args->arg2;
|
||||
const char *user_args = (const char *)args->arg3;
|
||||
if (!user_path) return -1;
|
||||
|
||||
char path_buf[256];
|
||||
int pi = 0;
|
||||
while (pi < 255 && user_path[pi]) {
|
||||
path_buf[pi] = user_path[pi];
|
||||
pi++;
|
||||
}
|
||||
path_buf[pi] = 0;
|
||||
|
||||
char args_buf[512];
|
||||
const char *args_ptr = NULL;
|
||||
if (user_args) {
|
||||
int ai = 0;
|
||||
while (ai < 511 && user_args[ai]) {
|
||||
args_buf[ai] = user_args[ai];
|
||||
ai++;
|
||||
}
|
||||
args_buf[ai] = 0;
|
||||
args_ptr = args_buf;
|
||||
}
|
||||
|
||||
return process_exec_replace_current(args->regs, path_buf, args_ptr);
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_waitpid(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int pid = (int)args->arg2;
|
||||
int *status = (int *)args->arg3;
|
||||
int options = (int)args->arg4;
|
||||
if (!proc) return -1;
|
||||
|
||||
int st = 0;
|
||||
int res = process_waitpid(proc->pid, pid, options, &st);
|
||||
if (res == -2) {
|
||||
if (options & 1) return 0; // WNOHANG
|
||||
return (uint64_t)-2;
|
||||
}
|
||||
if (res < 0) return (uint64_t)-1;
|
||||
if (status) *status = st;
|
||||
return (uint64_t)res;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_kill_signal(const syscall_args_t *args) {
|
||||
int pid = (int)args->arg2;
|
||||
int sig = (int)args->arg3;
|
||||
process_t *target;
|
||||
if (pid == -1) {
|
||||
target = process_get_current();
|
||||
} else {
|
||||
target = process_get_by_pid((uint32_t)pid);
|
||||
}
|
||||
if (!target) return -1;
|
||||
if (sig == 0) return 0;
|
||||
if (sig <= 0 || sig >= MAX_SIGNALS) return -1;
|
||||
|
||||
if (sig == 9) {
|
||||
process_terminate_with_status(target, 128 + sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
target->signal_pending |= (1ULL << (uint32_t)sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_sigaction(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int sig = (int)args->arg2;
|
||||
const k_sigaction_t *act = (const k_sigaction_t *)args->arg3;
|
||||
k_sigaction_t *oldact = (k_sigaction_t *)args->arg4;
|
||||
if (!proc || sig <= 0 || sig >= MAX_SIGNALS) return -1;
|
||||
|
||||
if (oldact) {
|
||||
oldact->sa_handler = proc->signal_handlers[sig];
|
||||
oldact->sa_mask = proc->signal_action_mask[sig];
|
||||
oldact->sa_flags = proc->signal_action_flags[sig];
|
||||
}
|
||||
if (act) {
|
||||
if (sig == SIGKILL_NUM && act->sa_handler != 0) {
|
||||
return -1;
|
||||
}
|
||||
proc->signal_handlers[sig] = act->sa_handler;
|
||||
proc->signal_action_mask[sig] = act->sa_mask;
|
||||
proc->signal_action_flags[sig] = act->sa_flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_sigprocmask(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
int how = (int)args->arg2;
|
||||
const uint64_t *set = (const uint64_t *)args->arg3;
|
||||
uint64_t *oldset = (uint64_t *)args->arg4;
|
||||
if (!proc) return -1;
|
||||
|
||||
if (oldset) {
|
||||
*oldset = proc->signal_mask;
|
||||
}
|
||||
if (!set) return 0;
|
||||
|
||||
if (how == 0) {
|
||||
proc->signal_mask |= *set;
|
||||
} else if (how == 1) {
|
||||
proc->signal_mask &= ~(*set);
|
||||
} else if (how == 2) {
|
||||
proc->signal_mask = *set;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
proc->signal_mask &= ~(1ULL << SIGKILL_NUM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_sigpending(const syscall_args_t *args) {
|
||||
process_t *proc = process_get_current();
|
||||
uint64_t *set = (uint64_t *)args->arg2;
|
||||
if (!proc || !set) return -1;
|
||||
*set = proc->signal_pending;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sys_cmd_tty_set_fg(const syscall_args_t *args) {
|
||||
int tty_id = (int)args->arg2;
|
||||
int pid = (int)args->arg3;
|
||||
|
|
@ -1694,61 +2087,69 @@ static uint64_t sys_cmd_tty_destroy(const syscall_args_t *args) {
|
|||
return tty_destroy(tty_id);
|
||||
}
|
||||
|
||||
#define SYS_CMD_TABLE_SIZE 70
|
||||
#define SYS_CMD_TABLE_SIZE 76
|
||||
static const syscall_handler_fn sys_cmd_table[SYS_CMD_TABLE_SIZE] = {
|
||||
[1] = sys_cmd_set_bg_color,
|
||||
[2] = sys_cmd_set_bg_pattern,
|
||||
[3] = sys_cmd_set_wallpaper_obsolete,
|
||||
[4] = sys_cmd_set_desktop_prop,
|
||||
[5] = sys_cmd_set_mouse_speed,
|
||||
[6] = sys_cmd_network_init,
|
||||
[7] = sys_cmd_get_desktop_prop,
|
||||
[8] = sys_cmd_get_mouse_speed,
|
||||
[9] = sys_cmd_get_wallpaper_thumb_obsolete,
|
||||
[10] = sys_cmd_clear_screen,
|
||||
[11] = sys_cmd_rtc_get,
|
||||
[12] = sys_cmd_reboot,
|
||||
[13] = sys_cmd_shutdown,
|
||||
[14] = sys_cmd_beep,
|
||||
[17] = sys_cmd_pci_list,
|
||||
[18] = sys_cmd_network_dhcp,
|
||||
[19] = sys_cmd_network_get_mac,
|
||||
[20] = sys_cmd_network_get_ip,
|
||||
[21] = sys_cmd_network_set_ip,
|
||||
[22] = sys_cmd_udp_send,
|
||||
[23] = sys_cmd_network_get_stats,
|
||||
[24] = sys_cmd_network_get_gateway,
|
||||
[25] = sys_cmd_network_get_dns,
|
||||
[26] = sys_cmd_icmp_ping,
|
||||
[27] = sys_cmd_network_is_init,
|
||||
[28] = sys_cmd_get_shell_config,
|
||||
[29] = sys_cmd_set_text_color,
|
||||
[30] = sys_cmd_network_has_ip,
|
||||
[31] = sys_cmd_set_wallpaper_path,
|
||||
[32] = sys_cmd_rtc_set,
|
||||
[33] = sys_cmd_tcp_connect,
|
||||
[34] = sys_cmd_tcp_send,
|
||||
[35] = sys_cmd_tcp_recv,
|
||||
[36] = sys_cmd_tcp_close,
|
||||
[37] = sys_cmd_dns_lookup,
|
||||
[38] = sys_cmd_set_dns,
|
||||
[39] = sys_cmd_net_unlock,
|
||||
[40] = sys_cmd_set_font,
|
||||
[41] = sys_cmd_set_raw_mode,
|
||||
[42] = sys_cmd_tcp_recv_nb,
|
||||
[47] = sys_cmd_set_resolution,
|
||||
[48] = sys_cmd_network_get_nic_name,
|
||||
[50] = sys_cmd_parallel_run,
|
||||
[60] = sys_cmd_tty_create,
|
||||
[61] = sys_cmd_tty_read_out,
|
||||
[62] = sys_cmd_tty_write_in,
|
||||
[63] = sys_cmd_tty_read_in,
|
||||
[64] = sys_cmd_spawn_process,
|
||||
[65] = sys_cmd_tty_set_fg,
|
||||
[66] = sys_cmd_tty_get_fg,
|
||||
[67] = sys_cmd_tty_kill_fg,
|
||||
[68] = sys_cmd_tty_kill_all,
|
||||
[69] = sys_cmd_tty_destroy,
|
||||
[SYSTEM_CMD_SET_BG_COLOR] = sys_cmd_set_bg_color,
|
||||
[SYSTEM_CMD_SET_BG_PATTERN] = sys_cmd_set_bg_pattern,
|
||||
[SYSTEM_CMD_SET_WALLPAPER] = sys_cmd_set_wallpaper,
|
||||
[SYSTEM_CMD_SET_DESKTOP_PROP] = sys_cmd_set_desktop_prop,
|
||||
[SYSTEM_CMD_SET_MOUSE_SPEED] = sys_cmd_set_mouse_speed,
|
||||
[SYSTEM_CMD_NETWORK_INIT] = sys_cmd_network_init,
|
||||
[SYSTEM_CMD_GET_DESKTOP_PROP] = sys_cmd_get_desktop_prop,
|
||||
[SYSTEM_CMD_GET_MOUSE_SPEED] = sys_cmd_get_mouse_speed,
|
||||
[SYSTEM_CMD_GET_WALLPAPER_THUMB] = sys_cmd_get_wallpaper_thumb,
|
||||
[SYSTEM_CMD_CLEAR_SCREEN] = sys_cmd_clear_screen,
|
||||
[SYSTEM_CMD_RTC_GET] = sys_cmd_rtc_get,
|
||||
[SYSTEM_CMD_REBOOT] = sys_cmd_reboot,
|
||||
[SYSTEM_CMD_SHUTDOWN] = sys_cmd_shutdown,
|
||||
[SYSTEM_CMD_BEEP] = sys_cmd_beep,
|
||||
[SYSTEM_CMD_GET_MEM_INFO] = sys_cmd_get_mem_info,
|
||||
[SYSTEM_CMD_GET_TICKS] = sys_cmd_get_ticks,
|
||||
[SYSTEM_CMD_PCI_LIST] = sys_cmd_pci_list,
|
||||
[SYSTEM_CMD_NETWORK_DHCP] = sys_cmd_network_dhcp,
|
||||
[SYSTEM_CMD_NETWORK_GET_MAC] = sys_cmd_network_get_mac,
|
||||
[SYSTEM_CMD_NETWORK_GET_IP] = sys_cmd_network_get_ip,
|
||||
[SYSTEM_CMD_NETWORK_SET_IP] = sys_cmd_network_set_ip,
|
||||
[SYSTEM_CMD_UDP_SEND] = sys_cmd_udp_send,
|
||||
[SYSTEM_CMD_NETWORK_GET_STATS] = sys_cmd_network_get_stats,
|
||||
[SYSTEM_CMD_NETWORK_GET_GATEWAY] = sys_cmd_network_get_gateway,
|
||||
[SYSTEM_CMD_NETWORK_GET_DNS] = sys_cmd_network_get_dns,
|
||||
[SYSTEM_CMD_ICMP_PING] = sys_cmd_icmp_ping,
|
||||
[SYSTEM_CMD_NETWORK_IS_INIT] = sys_cmd_network_is_init,
|
||||
[SYSTEM_CMD_GET_SHELL_CONFIG] = sys_cmd_get_shell_config,
|
||||
[SYSTEM_CMD_SET_TEXT_COLOR] = sys_cmd_set_text_color,
|
||||
[SYSTEM_CMD_NETWORK_HAS_IP] = sys_cmd_network_has_ip,
|
||||
[SYSTEM_CMD_SET_WALLPAPER_PATH] = sys_cmd_set_wallpaper_path,
|
||||
[SYSTEM_CMD_RTC_SET] = sys_cmd_rtc_set,
|
||||
[SYSTEM_CMD_TCP_CONNECT] = sys_cmd_tcp_connect,
|
||||
[SYSTEM_CMD_TCP_SEND] = sys_cmd_tcp_send,
|
||||
[SYSTEM_CMD_TCP_RECV] = sys_cmd_tcp_recv,
|
||||
[SYSTEM_CMD_TCP_CLOSE] = sys_cmd_tcp_close,
|
||||
[SYSTEM_CMD_DNS_LOOKUP] = sys_cmd_dns_lookup,
|
||||
[SYSTEM_CMD_SET_DNS] = sys_cmd_set_dns,
|
||||
[SYSTEM_CMD_NET_UNLOCK] = sys_cmd_net_unlock,
|
||||
[SYSTEM_CMD_SET_FONT] = sys_cmd_set_font,
|
||||
[SYSTEM_CMD_SET_RAW_MODE] = sys_cmd_set_raw_mode,
|
||||
[SYSTEM_CMD_TCP_RECV_NB] = sys_cmd_tcp_recv_nb,
|
||||
[SYSTEM_CMD_SET_RESOLUTION] = sys_cmd_set_resolution,
|
||||
[SYSTEM_CMD_NETWORK_GET_NIC_NAME] = sys_cmd_network_get_nic_name,
|
||||
[SYSTEM_CMD_PARALLEL_RUN] = sys_cmd_parallel_run,
|
||||
[SYSTEM_CMD_TTY_CREATE] = sys_cmd_tty_create,
|
||||
[SYSTEM_CMD_TTY_READ_OUT] = sys_cmd_tty_read_out,
|
||||
[SYSTEM_CMD_TTY_WRITE_IN] = sys_cmd_tty_write_in,
|
||||
[SYSTEM_CMD_TTY_READ_IN] = sys_cmd_tty_read_in,
|
||||
[SYSTEM_CMD_SPAWN] = sys_cmd_spawn_process,
|
||||
[SYSTEM_CMD_TTY_SET_FG] = sys_cmd_tty_set_fg,
|
||||
[SYSTEM_CMD_TTY_GET_FG] = sys_cmd_tty_get_fg,
|
||||
[SYSTEM_CMD_TTY_KILL_FG] = sys_cmd_tty_kill_fg,
|
||||
[SYSTEM_CMD_TTY_KILL_ALL] = sys_cmd_tty_kill_all,
|
||||
[SYSTEM_CMD_TTY_DESTROY] = sys_cmd_tty_destroy,
|
||||
[SYSTEM_CMD_EXEC] = sys_cmd_exec_process,
|
||||
[SYSTEM_CMD_WAITPID] = sys_cmd_waitpid,
|
||||
[SYSTEM_CMD_KILL_SIGNAL] = sys_cmd_kill_signal,
|
||||
[SYSTEM_CMD_SIGACTION] = sys_cmd_sigaction,
|
||||
[SYSTEM_CMD_SIGPROCMASK] = sys_cmd_sigprocmask,
|
||||
[SYSTEM_CMD_SIGPENDING] = sys_cmd_sigpending,
|
||||
};
|
||||
|
||||
static uint64_t handle_sys_write(const syscall_args_t *args) {
|
||||
|
|
@ -1871,6 +2272,49 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t syscall_maybe_deliver_signal(registers_t *regs) {
|
||||
process_t *proc = process_get_current();
|
||||
if (!proc || !proc->is_user) return (uint64_t)regs;
|
||||
|
||||
uint64_t pending = proc->signal_pending & ~proc->signal_mask;
|
||||
if (!pending) return (uint64_t)regs;
|
||||
|
||||
int sig = -1;
|
||||
for (int i = 1; i < MAX_SIGNALS; i++) {
|
||||
if (pending & (1ULL << (uint32_t)i)) {
|
||||
sig = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sig < 0) return (uint64_t)regs;
|
||||
|
||||
proc->signal_pending &= ~(1ULL << (uint32_t)sig);
|
||||
uint64_t handler = proc->signal_handlers[sig];
|
||||
int flags = proc->signal_action_flags[sig];
|
||||
|
||||
if (handler == 1) {
|
||||
return (uint64_t)regs;
|
||||
}
|
||||
|
||||
if (handler == 0 || sig == 9) {
|
||||
process_terminate_with_status(proc, 128 + sig);
|
||||
return process_schedule((uint64_t)regs);
|
||||
}
|
||||
|
||||
if (flags & SA_RESETHAND) {
|
||||
proc->signal_handlers[sig] = 0;
|
||||
proc->signal_action_mask[sig] = 0;
|
||||
proc->signal_action_flags[sig] = 0;
|
||||
}
|
||||
|
||||
uint64_t new_rsp = regs->rsp - sizeof(uint64_t);
|
||||
*((uint64_t *)new_rsp) = regs->rip;
|
||||
regs->rsp = new_rsp;
|
||||
regs->rip = handler;
|
||||
regs->rdi = (uint64_t)sig;
|
||||
return (uint64_t)regs;
|
||||
}
|
||||
|
||||
uint64_t syscall_handler_c(registers_t *regs) {
|
||||
uint64_t syscall_num = regs->rax;
|
||||
|
||||
|
|
@ -1899,13 +2343,13 @@ uint64_t syscall_handler_c(registers_t *regs) {
|
|||
}
|
||||
}
|
||||
|
||||
if (syscall_num == 5 && regs->rdi == 43) { // SYSTEM_CMD_YIELD
|
||||
if (syscall_num == SYS_SYSTEM && regs->rdi == SYSTEM_CMD_YIELD) {
|
||||
extern uint64_t process_schedule(uint64_t current_rsp);
|
||||
regs->rax = 0;
|
||||
return process_schedule((uint64_t)regs);
|
||||
}
|
||||
|
||||
if (syscall_num == 5 && regs->rdi == 46) { // SYSTEM_CMD_SLEEP
|
||||
if (syscall_num == SYS_SYSTEM && regs->rdi == SYSTEM_CMD_SLEEP) {
|
||||
uint32_t ms = (uint32_t)regs->rsi;
|
||||
process_t *proc = process_get_current();
|
||||
extern uint32_t wm_get_ticks(void);
|
||||
|
|
@ -1918,7 +2362,11 @@ uint64_t syscall_handler_c(registers_t *regs) {
|
|||
|
||||
// Normal syscalls
|
||||
regs->rax = syscall_handler_inner(regs);
|
||||
|
||||
// Return current RSP to assembly wrapper
|
||||
return (uint64_t)regs;
|
||||
|
||||
if (syscall_num == SYS_SYSTEM && regs->rdi == SYSTEM_CMD_WAITPID && regs->rax == (uint64_t)-2) {
|
||||
regs->rax = 0;
|
||||
return process_schedule((uint64_t)regs);
|
||||
}
|
||||
|
||||
return syscall_maybe_deliver_signal(regs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ typedef struct {
|
|||
#define SYS_WRITE 1
|
||||
#define SYS_GUI 3
|
||||
#define SYS_FS 4
|
||||
#define SYS_SYSTEM 5
|
||||
#define SYS_EXIT 60
|
||||
|
||||
// FS Commands
|
||||
|
|
@ -48,13 +49,74 @@ typedef struct {
|
|||
#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
|
||||
|
||||
#define SYSTEM_CMD_SET_BG_COLOR 1
|
||||
#define SYSTEM_CMD_SET_BG_PATTERN 2
|
||||
#define SYSTEM_CMD_SET_WALLPAPER 3
|
||||
#define SYSTEM_CMD_SET_DESKTOP_PROP 4
|
||||
#define SYSTEM_CMD_SET_MOUSE_SPEED 5
|
||||
#define SYSTEM_CMD_NETWORK_INIT 6
|
||||
#define SYSTEM_CMD_GET_DESKTOP_PROP 7
|
||||
#define SYSTEM_CMD_GET_MOUSE_SPEED 8
|
||||
#define SYSTEM_CMD_GET_WALLPAPER_THUMB 9
|
||||
#define SYSTEM_CMD_CLEAR_SCREEN 10
|
||||
#define SYSTEM_CMD_RTC_GET 11
|
||||
#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
|
||||
#define SYSTEM_CMD_NETWORK_GET_IP 20
|
||||
#define SYSTEM_CMD_NETWORK_SET_IP 21
|
||||
#define SYSTEM_CMD_UDP_SEND 22
|
||||
#define SYSTEM_CMD_NETWORK_GET_STATS 23
|
||||
#define SYSTEM_CMD_NETWORK_GET_GATEWAY 24
|
||||
#define SYSTEM_CMD_NETWORK_GET_DNS 25
|
||||
#define SYSTEM_CMD_ICMP_PING 26
|
||||
#define SYSTEM_CMD_NETWORK_IS_INIT 27
|
||||
#define SYSTEM_CMD_GET_SHELL_CONFIG 28
|
||||
#define SYSTEM_CMD_SET_TEXT_COLOR 29
|
||||
#define SYSTEM_CMD_NETWORK_HAS_IP 30
|
||||
#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
|
||||
#define SYSTEM_CMD_TCP_CLOSE 36
|
||||
#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_SET_RAW_MODE 41
|
||||
#define SYSTEM_CMD_TCP_RECV_NB 42
|
||||
#define SYSTEM_CMD_YIELD 43
|
||||
#define SYSTEM_CMD_SLEEP 46
|
||||
#define SYSTEM_CMD_SET_RESOLUTION 47
|
||||
#define SYSTEM_CMD_NETWORK_GET_NIC_NAME 48
|
||||
#define SYSTEM_CMD_PARALLEL_RUN 50
|
||||
#define SYSTEM_CMD_TTY_CREATE 60
|
||||
#define SYSTEM_CMD_TTY_READ_OUT 61
|
||||
#define SYSTEM_CMD_TTY_WRITE_IN 62
|
||||
#define SYSTEM_CMD_TTY_READ_IN 63
|
||||
#define SYSTEM_CMD_SPAWN 64
|
||||
#define SYSTEM_CMD_TTY_SET_FG 65
|
||||
#define SYSTEM_CMD_TTY_GET_FG 66
|
||||
#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
|
||||
|
||||
void syscall_init(void);
|
||||
uint64_t syscall_handler_c(registers_t *regs);
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ static void history_add(const char *line) {
|
|||
|
||||
static void get_time_string(char *out, int max_len) {
|
||||
int dt[6] = {0};
|
||||
sys_system(11, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0);
|
||||
char hh[4], mm[4];
|
||||
itoa(dt[3], hh);
|
||||
itoa(dt[4], mm);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
sys_system(10, 0, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_CLEAR_SCREEN, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int dt[6];
|
||||
if (sys_system(11, (uint64_t)dt, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0) == 0) {
|
||||
printf("Current Date: %d-%d-%d %d:%d:%d\n", dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]);
|
||||
} else {
|
||||
printf("Error: Could not retrieve date.\n");
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ int main(void) {
|
|||
if (!fb) return 1;
|
||||
|
||||
// Seed PRNG with system time (ticks)
|
||||
my_srand((unsigned int)sys_system(16, 0, 0, 0, 0));
|
||||
my_srand((unsigned int)sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0));
|
||||
|
||||
// Initialize perfect slope
|
||||
int max_h = WIN_H - 40; // max height
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
|||
int total = 0;
|
||||
int last_render = 0;
|
||||
if (progressive) inc_parse_offset = 0;
|
||||
long long last_data_tick = sys_system(16, 0, 0, 0, 0);
|
||||
long long last_data_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
|
||||
while (1) {
|
||||
int len = sys_tcp_recv_nb(dest_buf + total, max_len - 1 - total);
|
||||
|
|
@ -321,7 +321,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
|||
if (len == -2) break;
|
||||
|
||||
if (len == 0) {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now > last_data_tick + 1800) break; // 30 sec timeout
|
||||
|
||||
gui_event_t ev;
|
||||
|
|
@ -353,7 +353,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
|||
continue;
|
||||
}
|
||||
|
||||
last_data_tick = sys_system(16, 0, 0, 0, 0);
|
||||
last_data_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
total += len;
|
||||
if (total >= max_len - 1) break;
|
||||
|
||||
|
|
@ -461,7 +461,7 @@ static void decode_image(unsigned char *data, int len, RenderElement *el) {
|
|||
el->img_delays = malloc(frame_count * sizeof(int));
|
||||
el->img_frame_count = frame_count;
|
||||
el->img_current_frame = 0;
|
||||
el->next_frame_tick = sys_system(16, 0, 0, 0, 0) + (delays[0] * 60 / 1000);
|
||||
el->next_frame_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0) + (delays[0] * 60 / 1000);
|
||||
|
||||
uint32_t step_x = (img_w_orig << 16) / fit_w;
|
||||
uint32_t step_y = (img_h_orig << 16) / fit_h;
|
||||
|
|
@ -2116,7 +2116,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// Animated GIF progress
|
||||
bool gif_updated = false;
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
if (elements[i].tag == TAG_IMG && elements[i].img_frames && elements[i].img_frame_count > 1) {
|
||||
if (now >= elements[i].next_frame_tick) {
|
||||
|
|
|
|||
|
|
@ -769,14 +769,14 @@ static void control_panel_paint(ui_window_t win) {
|
|||
}
|
||||
|
||||
static void save_desktop_config(void) {
|
||||
sys_system(4 /*SET_DESKTOP_PROP*/, 1, desktop_snap_to_grid, 0, 0);
|
||||
sys_system(4, 2, desktop_auto_align, 0, 0);
|
||||
sys_system(4, 3, desktop_max_rows_per_col, 0, 0);
|
||||
sys_system(4, 4, desktop_max_cols, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 1, desktop_snap_to_grid, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 2, desktop_auto_align, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 3, desktop_max_rows_per_col, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 4, desktop_max_cols, 0, 0);
|
||||
}
|
||||
|
||||
static void save_mouse_config(void) {
|
||||
sys_system(5 /*SET_MOUSE_SPEED*/, mouse_speed, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_MOUSE_SPEED, mouse_speed, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int parse_ip(const char* str, net_ipv4_address_t* ip) {
|
||||
|
|
@ -802,11 +802,11 @@ static int parse_ip(const char* str, net_ipv4_address_t* ip) {
|
|||
}
|
||||
|
||||
static void fetch_kernel_state(void) {
|
||||
desktop_snap_to_grid = sys_system(7 /*GET_DESKTOP_PROP*/, 1, 0, 0, 0);
|
||||
desktop_auto_align = sys_system(7, 2, 0, 0, 0);
|
||||
desktop_max_rows_per_col = sys_system(7, 3, 0, 0, 0);
|
||||
desktop_max_cols = sys_system(7, 4, 0, 0, 0);
|
||||
mouse_speed = sys_system(8 /*GET_MOUSE_SPEED*/, 0, 0, 0, 0);
|
||||
desktop_snap_to_grid = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 1, 0, 0, 0);
|
||||
desktop_auto_align = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 2, 0, 0, 0);
|
||||
desktop_max_rows_per_col = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 3, 0, 0, 0);
|
||||
desktop_max_cols = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 4, 0, 0, 0);
|
||||
mouse_speed = sys_system(SYSTEM_CMD_GET_MOUSE_SPEED, 0, 0, 0, 0);
|
||||
|
||||
net_ipv4_address_t kip;
|
||||
if (sys_network_get_ip(&kip) == 0) {
|
||||
|
|
@ -889,7 +889,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
|||
if (disp_sel_color == 3) { bpp = 8; mode = 1; }
|
||||
if (disp_sel_color == 4) { bpp = 8; mode = 2; }
|
||||
|
||||
sys_system(47 /*SET_RESOLUTION*/, w, h, bpp, mode);
|
||||
sys_system(SYSTEM_CMD_SET_RESOLUTION, w, h, bpp, mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -912,28 +912,28 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
|||
uint32_t c = 0;
|
||||
if (i==0) c = COLOR_COFFEE; else if(i==1) c = COLOR_TEAL; else if(i==2) c = COLOR_GREEN;
|
||||
else if(i==3) c = COLOR_BLUE_BG; else if(i==4) c = COLOR_PURPLE; else if(i==5) c = COLOR_GREY;
|
||||
sys_system(1, c, 0, 0, 0); btn_wp_colors[i].pressed=false;
|
||||
sys_system(SYSTEM_CMD_SET_BG_COLOR, c, 0, 0, 0); btn_wp_colors[i].pressed=false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_patterns[0], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(2, (uint64_t)pattern_lumberjack, 0, 0, 0); btn_wp_patterns[0].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_BG_PATTERN, (uint64_t)pattern_lumberjack, 0, 0, 0); btn_wp_patterns[0].pressed=false;} return;
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_patterns[1], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(2, (uint64_t)pattern_blue_diamond, 0, 0, 0); btn_wp_patterns[1].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_BG_PATTERN, (uint64_t)pattern_blue_diamond, 0, 0, 0); btn_wp_patterns[1].pressed=false;} return;
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_apply, x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) {
|
||||
uint32_t cust = parse_rgb_separate(rgb_r, rgb_g, rgb_b);
|
||||
sys_system(1, cust, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_BG_COLOR, cust, 0, 0, 0);
|
||||
btn_wp_apply.pressed=false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i=0; i<wallpaper_count; i++) {
|
||||
if (wallpapers[i].valid && widget_button_handle_mouse(&btn_wp_thumbs[i], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(31, (uint64_t)wallpapers[i].path, 0, 0, 0); btn_wp_thumbs[i].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_WALLPAPER_PATH, (uint64_t)wallpapers[i].path, 0, 0, 0); btn_wp_thumbs[i].pressed=false;} return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -948,7 +948,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
|||
|
||||
if (widget_button_handle_mouse(&btn_net_init, x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) {
|
||||
if (sys_system(6, 0, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_NETWORK_INIT, 0, 0, 0, 0) == 0) {
|
||||
net_status[0] = 'I'; net_status[1] = 'n'; net_status[2] = 'i';
|
||||
net_status[3] = 't'; net_status[4] = 'e'; net_status[5] = 'd'; net_status[6] = 0;
|
||||
} else {
|
||||
|
|
@ -993,7 +993,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
|||
if (current_view == VIEW_FONTS) {
|
||||
for (int i=0; i<font_count; i++) {
|
||||
if (widget_button_handle_mouse(&btn_fonts[i], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { selected_font = i; sys_system(40 /*SET_FONT*/, (uint64_t)fonts[i].path, 0, 0, 0); btn_fonts[i].pressed=false;} return;
|
||||
if (is_click) { selected_font = i; sys_system(SYSTEM_CMD_SET_FONT, (uint64_t)fonts[i].path, 0, 0, 0); btn_fonts[i].pressed=false;} return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ int main(void) {
|
|||
ui_mark_dirty(win_taskman, 0, 0, 400, 480);
|
||||
|
||||
// Proper blocking sleep (200ms)
|
||||
sys_system(46, 200, 0, 0, 0); // SYSTEM_CMD_SLEEP
|
||||
sys_system(SYSTEM_CMD_SLEEP, 200, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void viewer_open_file(const char *path) {
|
|||
viewer_img_h = fit_h;
|
||||
viewer_has_image = (viewer_frame_count > 0);
|
||||
if (viewer_has_image) {
|
||||
viewer_next_frame_tick = sys_system(16, 0, 0, 0, 0) + (viewer_delays[0] * 60 / 1000);
|
||||
viewer_next_frame_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0) + (viewer_delays[0] * 60 / 1000);
|
||||
}
|
||||
}
|
||||
free(delays);
|
||||
|
|
@ -337,7 +337,7 @@ int main(int argc, char **argv) {
|
|||
win_w = ev.arg1;
|
||||
win_h = ev.arg2;
|
||||
resize_pending = true;
|
||||
last_resize_tick = sys_system(16, 0, 0, 0, 0);
|
||||
last_resize_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
// Fast background clear during active resize
|
||||
ui_draw_rect(win, 0, 0, win_w, win_h, 0xFF000000);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
|
|
@ -348,7 +348,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
} else {
|
||||
if (resize_pending) {
|
||||
uint64_t now = sys_system(16, 0, 0, 0, 0);
|
||||
uint64_t now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now > last_resize_tick + 10) {
|
||||
viewer_paint(win);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
|
|
@ -357,7 +357,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (viewer_has_image && viewer_frame_count > 1) {
|
||||
uint64_t now = sys_system(16, 0, 0, 0, 0);
|
||||
uint64_t now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now >= viewer_next_frame_tick) {
|
||||
viewer_current_frame = (viewer_current_frame + 1) % viewer_frame_count;
|
||||
viewer_next_frame_tick = now + (viewer_delays[viewer_current_frame] * 60 / 1000);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
224
src/userland/libc/posix_process.c
Normal file
224
src/userland/libc/posix_process.c
Normal 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
15
src/userland/libc/sys/wait.h
Normal file
15
src/userland/libc/sys/wait.h
Normal 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
sys_system(14, 392, 400, 0, 0);
|
||||
sys_system(SYSTEM_CMD_BEEP, 392, 400, 0, 0);
|
||||
printf("BEEP!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ static long long sw_start_ticks = 0;
|
|||
static long long sw_elapsed_ticks = 0;
|
||||
static bool sw_running = false;
|
||||
|
||||
static long long sys_ticks_now(void) {
|
||||
return sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void format_time(char *buf, int h, int m, int s) {
|
||||
buf[0] = '0' + (h / 10);
|
||||
buf[1] = '0' + (h % 10);
|
||||
|
|
@ -55,7 +59,7 @@ static void format_time(char *buf, int h, int m, int s) {
|
|||
static void update_rtc_state(void) {
|
||||
int dt[6];
|
||||
int old_s = cur_s;
|
||||
sys_system(11, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0);
|
||||
cur_y = dt[0]; cur_mon = dt[1]; cur_d = dt[2];
|
||||
cur_h = dt[3]; cur_m = dt[4]; cur_s = dt[5];
|
||||
|
||||
|
|
@ -123,7 +127,7 @@ static void clock_paint(void) {
|
|||
draw_btn((WIN_W - 120) / 2, 195, 120, 28, "Apply changes", false);
|
||||
|
||||
} else if (current_tab == TAB_TIMER) {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_ticks_now();
|
||||
int display_h = timer_h, display_m = timer_m, display_s = timer_s;
|
||||
|
||||
if (timer_running) {
|
||||
|
|
@ -131,7 +135,7 @@ static void clock_paint(void) {
|
|||
if (rem <= 0) {
|
||||
timer_running = false;
|
||||
display_h = display_m = display_s = 0;
|
||||
for(int i=0; i<3; i++) sys_system(14, 440, 200, 0, 0);
|
||||
for (int i = 0; i < 3; i++) sys_system(SYSTEM_CMD_BEEP, 440, 200, 0, 0);
|
||||
} else {
|
||||
int s = rem / 60;
|
||||
display_h = s / 3600;
|
||||
|
|
@ -157,7 +161,7 @@ static void clock_paint(void) {
|
|||
|
||||
} else if (current_tab == TAB_STOPWATCH) {
|
||||
long long elapsed = sw_elapsed_ticks;
|
||||
if (sw_running) elapsed += (sys_system(16, 0, 0, 0, 0) - sw_start_ticks);
|
||||
if (sw_running) elapsed += (sys_ticks_now() - sw_start_ticks);
|
||||
|
||||
int ms_val = (elapsed % 60) * 1000 / 60;
|
||||
int s_val = (elapsed / 60) % 60;
|
||||
|
|
@ -207,7 +211,7 @@ static void clock_click(int x, int y) {
|
|||
else if (x >= ax_clock + 73 && x <= ax_clock + 110) adj_s = (adj_s + 59) % 60;
|
||||
} else if (x >= (WIN_W - 120) / 2 && x <= (WIN_W + 120) / 2 && y >= 195 && y <= 223) {
|
||||
int dt[6] = {cur_y, cur_mon, cur_d, adj_h, adj_m, adj_s};
|
||||
sys_system(32, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_SET, (uint64_t)dt, 0, 0, 0);
|
||||
}
|
||||
} else if (current_tab == TAB_TIMER) {
|
||||
if (!timer_running) {
|
||||
|
|
@ -225,16 +229,16 @@ static void clock_click(int x, int y) {
|
|||
if (!timer_running) {
|
||||
if (timer_h > 0 || timer_m > 0 || timer_s > 0) {
|
||||
timer_running = true;
|
||||
timer_end_ticks = sys_system(16, 0, 0, 0, 0) + (long long)(timer_h * 3600 + timer_m * 60 + timer_s) * 60;
|
||||
timer_end_ticks = sys_ticks_now() + (long long)(timer_h * 3600 + timer_m * 60 + timer_s) * 60;
|
||||
}
|
||||
} else timer_running = false;
|
||||
}
|
||||
} else if (current_tab == TAB_STOPWATCH) {
|
||||
if (x >= 20 && x <= 110 && y >= 150 && y <= 180) {
|
||||
if (sw_running) { sw_elapsed_ticks += (sys_system(16, 0, 0, 0, 0) - sw_start_ticks); sw_running = false; }
|
||||
else { sw_start_ticks = sys_system(16, 0, 0, 0, 0); sw_running = true; }
|
||||
if (sw_running) { sw_elapsed_ticks += (sys_ticks_now() - sw_start_ticks); sw_running = false; }
|
||||
else { sw_start_ticks = sys_ticks_now(); sw_running = true; }
|
||||
} else if (x >= 140 && x <= 230 && y >= 150 && y <= 180) {
|
||||
sw_elapsed_ticks = 0; sw_start_ticks = sys_system(16, 0, 0, 0, 0);
|
||||
sw_elapsed_ticks = 0; sw_start_ticks = sys_ticks_now();
|
||||
}
|
||||
}
|
||||
clock_paint();
|
||||
|
|
@ -254,7 +258,7 @@ int main(void) {
|
|||
else if (ev.type == GUI_EVENT_CLICK) clock_click(ev.arg1, ev.arg2);
|
||||
else if (ev.type == GUI_EVENT_CLOSE) sys_exit(0);
|
||||
} else {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_ticks_now();
|
||||
if (now - last_rep >= 6) { clock_paint(); ui_mark_dirty(win_clock, 0, 0, WIN_W, WIN_H); last_rep = now; }
|
||||
sleep(10);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
uint64_t mem[2];
|
||||
if (sys_system(15, (uint64_t)mem, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_GET_MEM_INFO, (uint64_t)mem, 0, 0, 0) == 0) {
|
||||
printf("Memory Info:\n");
|
||||
printf("Total: %d MB\n", (int)(mem[0] / 1024 / 1024));
|
||||
printf("Used: %d MB\n", (int)(mem[1] / 1024 / 1024));
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ typedef struct {
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int count = sys_system(17, 0, 0, 0, 0);
|
||||
int count = sys_system(SYSTEM_CMD_PCI_LIST, 0, 0, 0, 0);
|
||||
if (count < 0) {
|
||||
printf("Error: Could not retrieve PCI device count.\n");
|
||||
return 1;
|
||||
|
|
@ -23,7 +23,7 @@ int main(int argc, char **argv) {
|
|||
printf("---------------------------\n");
|
||||
for (int i = 0; i < count; i++) {
|
||||
pci_info_t info;
|
||||
if (sys_system(17, (uint64_t)&info, i, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_PCI_LIST, (uint64_t)&info, i, 0, 0) == 0) {
|
||||
printf("[%d] Vendor:%04x Device:%04x Class:%02x Sub:%02x\n",
|
||||
i, info.vendor, info.device, info.class_code, info.subclass);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Rebooting...\n");
|
||||
sys_system(12, 0, 0, 0, 0); // SYSTEM_CMD_REBOOT
|
||||
sys_system(SYSTEM_CMD_REBOOT, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Shutting down...\n");
|
||||
sys_system(13, 0, 0, 0, 0); // SYSTEM_CMD_SHUTDOWN
|
||||
sys_system(SYSTEM_CMD_SHUTDOWN, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue