From 385b7d7a1339a3392bc8f20b6231d8cea39961f4 Mon Sep 17 00:00:00 2001 From: Karina Date: Fri, 30 Jan 2026 08:10:08 +0400 Subject: [PATCH] wip(termosh); strspn strpbrk and strtok in string.h; --- CMakeLists.txt | 2 +- ROADMAP.md | 2 +- kernel/src/arch/x86_64/interrupts.c | 14 +++++++- userspace/CMakeLists.txt | 3 +- userspace/init/src/main.c | 8 ++--- userspace/libterm/inc/string.h | 5 ++- userspace/libterm/src/string.c | 49 ++++++++++++++++++++++++++ userspace/termosh/CMakeLists.txt | 9 +++++ userspace/termosh/inc/handlers.h | 6 ++++ userspace/termosh/inc/parser.h | 9 +++++ userspace/termosh/inc/tokens.h | 16 +++++++++ userspace/termosh/src/handlers/misc.c | 5 +++ userspace/termosh/src/main.c | 29 +++++++++++++++ userspace/termosh/src/modules/parser.c | 49 ++++++++++++++++++++++++++ 14 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 userspace/termosh/CMakeLists.txt create mode 100644 userspace/termosh/inc/handlers.h create mode 100644 userspace/termosh/inc/parser.h create mode 100644 userspace/termosh/inc/tokens.h create mode 100644 userspace/termosh/src/handlers/misc.c create mode 100644 userspace/termosh/src/main.c create mode 100644 userspace/termosh/src/modules/parser.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ceab63..c6f37d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE) COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR} COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\"" WORKING_DIRECTORY ${INITRAMFS_SRC_DIR} - DEPENDS ${INIT_FILES} init debug + DEPENDS ${INIT_FILES} init debug termosh VERBATIM COMMENT "Packing initramfs to cpio..." ) diff --git a/ROADMAP.md b/ROADMAP.md index 872e0ec..f2a24ed 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,7 +23,7 @@ ### v0.5.4 (The Shell Update) *Focus: Interactive Userspace* -- [ ] **Userspace Shell (`ush`)** +- [ ] **Userspace Shell (`termosh`)** - Porting `ksh` logic into a standalone `.hot` binary. - Standard I/O abstraction (stdin/stdout) to pass keyboard input to active process. - [ ] **Basic Utils** diff --git a/kernel/src/arch/x86_64/interrupts.c b/kernel/src/arch/x86_64/interrupts.c index 1be1d37..ccf10db 100644 --- a/kernel/src/arch/x86_64/interrupts.c +++ b/kernel/src/arch/x86_64/interrupts.c @@ -1,18 +1,30 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2025 0xKarinyash -#include "drivers/timer.h" #include #include +#include #include +#include +#include #include +#include #include +extern task* curr_task; void isr_handler_c(Registers *regs) { if (regs->int_no == 3) { return print_regs(); } + if ((regs->cs & 3) != 0) { + kprintf("\n[Dewar] Process '%s' (PID %d) Segmentation Fault at %X\n", + curr_task->proc->name, curr_task->proc->pid, regs->rip); + curr_task->task_state = DEAD; + sys_exit(-1); + sched_next((u64)regs); + return; + } panic_exception(regs); } diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index 18c1f0d..1408b96 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -9,4 +9,5 @@ message(STATUS "Building termOS's userspace") add_subdirectory(libterm) add_subdirectory(init) -add_subdirectory(debug) \ No newline at end of file +add_subdirectory(debug) +add_subdirectory(termosh) \ No newline at end of file diff --git a/userspace/init/src/main.c b/userspace/init/src/main.c index 19bafbd..61398c1 100644 --- a/userspace/init/src/main.c +++ b/userspace/init/src/main.c @@ -6,9 +6,7 @@ #include int main() { - wait(spawn("debug")); - printf("\nStill here?\n"); - while (1) { - printf("1"); - } + wait(spawn("termosh")); // TODO: read .cfg and spawn what stated there + printf("\nbaiii"); + return 0; } \ No newline at end of file diff --git a/userspace/libterm/inc/string.h b/userspace/libterm/inc/string.h index 0344051..ccfd26d 100644 --- a/userspace/libterm/inc/string.h +++ b/userspace/libterm/inc/string.h @@ -10,4 +10,7 @@ i32 strcmp(const char *s1, const char *s2); i32 strncmp(const char* s1, const char* s2, u64 n); char* strcpy(char* dest, const char* src); char* strncpy(char* dest, const char* src, u64 n); -u64 strlen(const char* str); \ No newline at end of file +u64 strlen(const char* str); +u64 strspn(const char* s, const char* accept); +char* strpbrk(const char* s, const char* accept); +char* strtok(char *s, const char* delim); \ No newline at end of file diff --git a/userspace/libterm/src/string.c b/userspace/libterm/src/string.c index ac5f7e1..2594541 100644 --- a/userspace/libterm/src/string.c +++ b/userspace/libterm/src/string.c @@ -3,6 +3,8 @@ #include +static char* olds; + void *memset(void *ptr, int value, usize num) { u8 *p = (u8 *)ptr; while (num--) { @@ -74,4 +76,51 @@ u64 strlen(const char* str) { u64 res = 0; for (res = 0; str[res]; res++); return res; +} + +static inline int is_in_set(char c, const char* set) { + while (*set) { + if (*set == c) return 1; + set++; + } + return 0; +} + +u64 strspn(const char* s, const char* accept) { + u64 count = 0; + while (*s && is_in_set(*s, accept)) { + count++; + s++; + } + return count; +} + +char* strpbrk(const char* s, const char* accept) { + while (*s) { + if (is_in_set(*s, accept)) { + return (char*)s; + } + s++; + } + return nullptr; +} +// took from https://github.com/walac/glibc/blob/master/string/strtok.c +char* strtok(char *s, const char* delim) { + char* token; + if (s == nullptr) s = olds; + s += strspn(s, delim); + if (*s == '\0') { + olds = s; + return nullptr; + } + + token = s; + s = strpbrk(token, delim); + if (s == nullptr) olds = token + strlen(token); + else { + *s = '\0'; + olds = s + 1; + } + + return token; } \ No newline at end of file diff --git a/userspace/termosh/CMakeLists.txt b/userspace/termosh/CMakeLists.txt new file mode 100644 index 0000000..d0051f5 --- /dev/null +++ b/userspace/termosh/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.20) +project(termOSh LANGUAGES C) + +file(GLOB_RECURSE TERMOSH_SOURCES "src/*.c") + +add_termos_executable(termosh "${TERMOSH_SOURCES}") +target_include_directories(termosh PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/inc" +) \ No newline at end of file diff --git a/userspace/termosh/inc/handlers.h b/userspace/termosh/inc/handlers.h new file mode 100644 index 0000000..7389a22 --- /dev/null +++ b/userspace/termosh/inc/handlers.h @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +void not_implemented_yet(); \ No newline at end of file diff --git a/userspace/termosh/inc/parser.h b/userspace/termosh/inc/parser.h new file mode 100644 index 0000000..d3a884e --- /dev/null +++ b/userspace/termosh/inc/parser.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +#include "tokens.h" + +termosh_token char2token(char* token); +int tokenize(char* buffer, char* tokens[], int max_tokens); \ No newline at end of file diff --git a/userspace/termosh/inc/tokens.h b/userspace/termosh/inc/tokens.h new file mode 100644 index 0000000..011c354 --- /dev/null +++ b/userspace/termosh/inc/tokens.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#pragma once + +typedef enum { + TOKEN_EMPTY, + TOKEN_NULL, + TOKEN_ILLEGAL, + + TOKEN_QUIT, + TOKEN_CLEAR, + TOKEN_HELP, + TOKEN_SPAWN, + +} termosh_token; diff --git a/userspace/termosh/src/handlers/misc.c b/userspace/termosh/src/handlers/misc.c new file mode 100644 index 0000000..833c1e9 --- /dev/null +++ b/userspace/termosh/src/handlers/misc.c @@ -0,0 +1,5 @@ +#include + +void not_implemented_yet() { + printf("Not implemented yet!\n"); +} \ No newline at end of file diff --git a/userspace/termosh/src/main.c b/userspace/termosh/src/main.c new file mode 100644 index 0000000..9e957a9 --- /dev/null +++ b/userspace/termosh/src/main.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash + +#include "tokens.h" +#include "parser.h" +#include "handlers.h" + +#include + +#define BUFFER_SIZE 512 + +int main() { + while (true) { + printf("termosh_> "); + char cmdbuff[BUFFER_SIZE]; + gets_s(cmdbuff, BUFFER_SIZE); + char* tokens[BUFFER_SIZE]; + int tokens_count = tokenize(cmdbuff, tokens, BUFFER_SIZE); + if (tokens_count < 1) continue; + termosh_token token = char2token(tokens[0]); + switch (token) { + case TOKEN_QUIT: return 0; + case TOKEN_CLEAR: not_implemented_yet(); break; + case TOKEN_HELP: not_implemented_yet(); break; + case TOKEN_SPAWN: not_implemented_yet(); break; + default: printf("Unknown command\n"); break; + } + } +} \ No newline at end of file diff --git a/userspace/termosh/src/modules/parser.c b/userspace/termosh/src/modules/parser.c new file mode 100644 index 0000000..a859393 --- /dev/null +++ b/userspace/termosh/src/modules/parser.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKarinyash +#include + +#include "parser.h" +#include "tokens.h" + +static const char* delim = " \t\r\n"; + +typedef struct { + char* str; + termosh_token token; +} termosh_token_map; + +static const termosh_token_map token_map[] = { + {"q", TOKEN_QUIT}, + {"quit", TOKEN_QUIT}, + {"exit", TOKEN_QUIT}, + + {"clear", TOKEN_CLEAR}, + + {"help", TOKEN_HELP}, + {"spawn", TOKEN_SPAWN}, + + {nullptr, TOKEN_NULL} +}; + +termosh_token char2token(char* token) { + for (int i = 0; token_map[i].str != nullptr; i++) { + if (strcmp(token, token_map[i].str) == 0) { + return token_map[i].token; + } + } + + return TOKEN_ILLEGAL; +} + +int tokenize(char* buffer, char* tokens[], int max_tokens) { + char* token = strtok(buffer, delim); + + int i = 0; + while (token != nullptr && i < max_tokens) { + tokens[i] = token; + token = strtok(nullptr, delim); + i++; + } + + return i; +}