diff --git a/src/sys/process.c b/src/sys/process.c index 3261c32..9dbb2bb 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -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 diff --git a/src/sys/process.h b/src/sys/process.h index 632afc8..820734d 100644 --- a/src/sys/process.h +++ b/src/sys/process.h @@ -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 diff --git a/src/sys/syscall.c b/src/sys/syscall.c index 37dccff..e31fb8e 100644 --- a/src/sys/syscall.c +++ b/src/sys/syscall.c @@ -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); } diff --git a/src/sys/syscall.h b/src/sys/syscall.h index 03a5c12..d98d030 100644 --- a/src/sys/syscall.h +++ b/src/sys/syscall.h @@ -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); diff --git a/src/userland/cli/bsh.c b/src/userland/cli/bsh.c index c5bfe80..564766e 100644 --- a/src/userland/cli/bsh.c +++ b/src/userland/cli/bsh.c @@ -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); diff --git a/src/userland/cli/clear.c b/src/userland/cli/clear.c index 6a1de8b..d0211e8 100644 --- a/src/userland/cli/clear.c +++ b/src/userland/cli/clear.c @@ -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; } diff --git a/src/userland/cli/date.c b/src/userland/cli/date.c index f19a51d..cc32754 100644 --- a/src/userland/cli/date.c +++ b/src/userland/cli/date.c @@ -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"); diff --git a/src/userland/cli/sort.c b/src/userland/cli/sort.c index d8cd07e..f1fab48 100644 --- a/src/userland/cli/sort.c +++ b/src/userland/cli/sort.c @@ -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 diff --git a/src/userland/gui/browser.c b/src/userland/gui/browser.c index ab7aa7f..7c29386 100644 --- a/src/userland/gui/browser.c +++ b/src/userland/gui/browser.c @@ -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) { diff --git a/src/userland/gui/settings.c b/src/userland/gui/settings.c index 38b136c..3d9d690 100644 --- a/src/userland/gui/settings.c +++ b/src/userland/gui/settings.c @@ -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 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); diff --git a/src/userland/libc/errno.h b/src/userland/libc/errno.h index 3901593..396ca00 100644 --- a/src/userland/libc/errno.h +++ b/src/userland/libc/errno.h @@ -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 diff --git a/src/userland/libc/fcntl.h b/src/userland/libc/fcntl.h index 7cc4fd8..6bb56c1 100644 --- a/src/userland/libc/fcntl.h +++ b/src/userland/libc/fcntl.h @@ -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 diff --git a/src/userland/libc/libui.c b/src/userland/libc/libui.c index 7366992..3a87672 100644 --- a/src/userland/libc/libui.c +++ b/src/userland/libc/libui.c @@ -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 }; diff --git a/src/userland/libc/libui.h b/src/userland/libc/libui.h index e96c237..6d98091 100644 --- a/src/userland/libc/libui.h +++ b/src/userland/libc/libui.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 diff --git a/src/userland/libc/posix_fs.c b/src/userland/libc/posix_fs.c index d85c19a..66c877b 100644 --- a/src/userland/libc/posix_fs.c +++ b/src/userland/libc/posix_fs.c @@ -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; diff --git a/src/userland/libc/posix_io.c b/src/userland/libc/posix_io.c index 7e0a8fe..d970590 100644 --- a/src/userland/libc/posix_io.c +++ b/src/userland/libc/posix_io.c @@ -1,14 +1,98 @@ #include #include +#include #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; + } +} diff --git a/src/userland/libc/posix_process.c b/src/userland/libc/posix_process.c new file mode 100644 index 0000000..0d15f05 --- /dev/null +++ b/src/userland/libc/posix_process.c @@ -0,0 +1,224 @@ +#include +#include + +#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(); + } +} diff --git a/src/userland/libc/signal.c b/src/userland/libc/signal.c index 105f2bc..8c3b95c 100644 --- a/src/userland/libc/signal.c +++ b/src/userland/libc/signal.c @@ -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; } diff --git a/src/userland/libc/signal.h b/src/userland/libc/signal.h index 9514e1c..671f8c1 100644 --- a/src/userland/libc/signal.h +++ b/src/userland/libc/signal.h @@ -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 diff --git a/src/userland/libc/stdio.c b/src/userland/libc/stdio.c index edaee8d..510d589 100644 --- a/src/userland/libc/stdio.c +++ b/src/userland/libc/stdio.c @@ -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; } diff --git a/src/userland/libc/stdlib.c b/src/userland/libc/stdlib.c index 2df15fb..a471ec4 100644 --- a/src/userland/libc/stdlib.c +++ b/src/userland/libc/stdlib.c @@ -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) { diff --git a/src/userland/libc/sys/stat.h b/src/userland/libc/sys/stat.h index 318d322..e3cfdb8 100644 --- a/src/userland/libc/sys/stat.h +++ b/src/userland/libc/sys/stat.h @@ -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); diff --git a/src/userland/libc/sys/types.h b/src/userland/libc/sys/types.h index 4d680b5..da5815b 100644 --- a/src/userland/libc/sys/types.h +++ b/src/userland/libc/sys/types.h @@ -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 diff --git a/src/userland/libc/sys/wait.h b/src/userland/libc/sys/wait.h new file mode 100644 index 0000000..6e0133c --- /dev/null +++ b/src/userland/libc/sys/wait.h @@ -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 diff --git a/src/userland/libc/syscall.c b/src/userland/libc/syscall.c index 5e433c3..f5068c4 100644 --- a/src/userland/libc/syscall.c +++ b/src/userland/libc/syscall.c @@ -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); } diff --git a/src/userland/libc/syscall.h b/src/userland/libc/syscall.h index f6f168a..6b03bd9 100644 --- a/src/userland/libc/syscall.h +++ b/src/userland/libc/syscall.h @@ -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); diff --git a/src/userland/libc/unistd.h b/src/userland/libc/unistd.h index e1c70b8..36d7081 100644 --- a/src/userland/libc/unistd.h +++ b/src/userland/libc/unistd.h @@ -1,6 +1,7 @@ #ifndef BOREDOS_LIBC_UNISTD_H #define BOREDOS_LIBC_UNISTD_H +#include #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 diff --git a/src/userland/sys/beep.c b/src/userland/sys/beep.c index 7ae4355..5745bcb 100644 --- a/src/userland/sys/beep.c +++ b/src/userland/sys/beep.c @@ -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; } diff --git a/src/userland/sys/clock.c b/src/userland/sys/clock.c index 882cb08..a733c7d 100644 --- a/src/userland/sys/clock.c +++ b/src/userland/sys/clock.c @@ -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); } diff --git a/src/userland/sys/meminfo.c b/src/userland/sys/meminfo.c index 1e11822..fa4f15f 100644 --- a/src/userland/sys/meminfo.c +++ b/src/userland/sys/meminfo.c @@ -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)); diff --git a/src/userland/sys/pci_list.c b/src/userland/sys/pci_list.c index faeeabc..1198f60 100644 --- a/src/userland/sys/pci_list.c +++ b/src/userland/sys/pci_list.c @@ -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); } diff --git a/src/userland/sys/reboot.c b/src/userland/sys/reboot.c index 214afd6..edf5eea 100644 --- a/src/userland/sys/reboot.c +++ b/src/userland/sys/reboot.c @@ -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; } diff --git a/src/userland/sys/shutdown.c b/src/userland/sys/shutdown.c index 8825593..f13bfcd 100644 --- a/src/userland/sys/shutdown.c +++ b/src/userland/sys/shutdown.c @@ -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; }