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

224 lines
4.6 KiB
C

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