From 5a77cc3bdfe9bef5030867a3c2f1ec78f164acc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=A5rdbrink?= Date: Sat, 2 Aug 2025 00:10:31 +0200 Subject: [PATCH] Add signal handlers and background processes --- main.odin | 1 + shell/shell.odin | 49 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/main.odin b/main.odin index 8595c07..a684a3e 100644 --- a/main.odin +++ b/main.odin @@ -26,6 +26,7 @@ main :: proc() { } buf: [INPUT_MAX]byte + shell.init_shell() for true { prompt := shell.get_prompt() diff --git a/shell/shell.odin b/shell/shell.odin index 8abfe91..f6bd75d 100644 --- a/shell/shell.odin +++ b/shell/shell.odin @@ -1,5 +1,7 @@ package shell +import "base:runtime" + import "core:fmt" import "core:strings" import "core:sys/posix" @@ -14,6 +16,45 @@ ShellState :: enum { Stop } +maybe_foreground_pid: Maybe(posix.pid_t) = nil +ctx: runtime.Context + +handle_ctrl_c :: proc"c"(sig: posix.Signal) { + foreground_pid, foreground_running := maybe_foreground_pid.? + + if foreground_running { + posix.kill(foreground_pid, .SIGINT) + } else { + // Clear prompt + } +} + +handle_backround_process :: proc"c"(sig: posix.Signal) { + context = ctx + foreground_pid, foreground_running := maybe_foreground_pid.? + + if foreground_running do return + + CHILD_PROCESS :: -1 + background_pid := posix.waitpid(CHILD_PROCESS, nil, {.NOHANG}) + + if background_pid > 0 && background_pid != foreground_pid { + fmt.printf("skal: [%d] done", background_pid) + // Clear prompt + } + + if foreground_pid == background_pid { + maybe_foreground_pid = nil + } + +} + +init_shell :: proc() { + ctx = context + posix.signal(.SIGINT, handle_ctrl_c) + posix.signal(.SIGCHLD, handle_backround_process) +} + get_prompt :: proc() -> string { dir := os.get_current_directory(context.temp_allocator) home := string(posix.getenv("HOME")) @@ -32,8 +73,8 @@ get_prompt :: proc() -> string { user = string(pw.pw_name) } - promt_parts := []string {user, " :: ", dir, " » "} - prompt, err := strings.concatenate(promt_parts[:], context.temp_allocator) + prompt_parts := []string {user, " :: ", dir, " » "} + prompt, err := strings.concatenate(prompt_parts[:], context.temp_allocator) log.assertf(err == nil, "Memory allocation failed") return prompt @@ -161,9 +202,11 @@ execute_cmd_seq :: proc(cmd_seq: ^parser.CommandSequence) { pipe_command(&pipe_seq, nil, len(pipe_seq.commands)-1) case: // Parent if pipe_seq.is_background { - fmt.printf("Background process: [%d]\n", pid) + fmt.printf("skal: [%d] spawned\n", pid) posix.waitpid(pid, nil, { .NOHANG}) } else { + maybe_foreground_pid = pid + status: i32 posix.waitpid(pid, &status, { .UNTRACED, .CONTINUED })