mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 16
This commit is contained in:
@@ -3,35 +3,127 @@
|
||||
#include <clks/tty.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_SC_ALT 0x38U
|
||||
#define CLKS_SC_F1 0x3BU
|
||||
#define CLKS_SC_F2 0x3CU
|
||||
#define CLKS_SC_F3 0x3DU
|
||||
#define CLKS_SC_F4 0x3EU
|
||||
#define CLKS_SC_ALT 0x38U
|
||||
#define CLKS_SC_LSHIFT 0x2AU
|
||||
#define CLKS_SC_RSHIFT 0x36U
|
||||
#define CLKS_SC_F1 0x3BU
|
||||
#define CLKS_SC_F2 0x3CU
|
||||
#define CLKS_SC_F3 0x3DU
|
||||
#define CLKS_SC_F4 0x3EU
|
||||
#define CLKS_SC_EXT_PREFIX 0xE0U
|
||||
|
||||
#define CLKS_KBD_INPUT_CAP 256U
|
||||
|
||||
static const char clks_kbd_map[128] = {
|
||||
[2] = '1', [3] = '2', [4] = '3', [5] = '4', [6] = '5', [7] = '6', [8] = '7', [9] = '8',
|
||||
[10] = '9', [11] = '0', [12] = '-', [13] = '=', [14] = '\b', [15] = '\t',
|
||||
[16] = 'q', [17] = 'w', [18] = 'e', [19] = 'r', [20] = 't', [21] = 'y', [22] = 'u', [23] = 'i',
|
||||
[24] = 'o', [25] = 'p', [26] = '[', [27] = ']', [28] = '\n',
|
||||
[30] = 'a', [31] = 's', [32] = 'd', [33] = 'f', [34] = 'g', [35] = 'h', [36] = 'j', [37] = 'k',
|
||||
[38] = 'l', [39] = ';', [40] = '\'', [41] = '`', [43] = '\\',
|
||||
[44] = 'z', [45] = 'x', [46] = 'c', [47] = 'v', [48] = 'b', [49] = 'n', [50] = 'm',
|
||||
[51] = ',', [52] = '.', [53] = '/', [57] = ' '
|
||||
};
|
||||
|
||||
static const char clks_kbd_shift_map[128] = {
|
||||
[2] = '!', [3] = '@', [4] = '#', [5] = '$', [6] = '%', [7] = '^', [8] = '&', [9] = '*',
|
||||
[10] = '(', [11] = ')', [12] = '_', [13] = '+', [14] = '\b', [15] = '\t',
|
||||
[16] = 'Q', [17] = 'W', [18] = 'E', [19] = 'R', [20] = 'T', [21] = 'Y', [22] = 'U', [23] = 'I',
|
||||
[24] = 'O', [25] = 'P', [26] = '{', [27] = '}', [28] = '\n',
|
||||
[30] = 'A', [31] = 'S', [32] = 'D', [33] = 'F', [34] = 'G', [35] = 'H', [36] = 'J', [37] = 'K',
|
||||
[38] = 'L', [39] = ':', [40] = '"', [41] = '~', [43] = '|',
|
||||
[44] = 'Z', [45] = 'X', [46] = 'C', [47] = 'V', [48] = 'B', [49] = 'N', [50] = 'M',
|
||||
[51] = '<', [52] = '>', [53] = '?', [57] = ' '
|
||||
};
|
||||
|
||||
static char clks_kbd_input_queue[CLKS_KBD_INPUT_CAP];
|
||||
static u16 clks_kbd_input_head = 0U;
|
||||
static u16 clks_kbd_input_tail = 0U;
|
||||
static u16 clks_kbd_input_count = 0U;
|
||||
|
||||
static clks_bool clks_kbd_alt_down = CLKS_FALSE;
|
||||
static clks_bool clks_kbd_lshift_down = CLKS_FALSE;
|
||||
static clks_bool clks_kbd_rshift_down = CLKS_FALSE;
|
||||
static clks_bool clks_kbd_e0_prefix = CLKS_FALSE;
|
||||
static u64 clks_kbd_hotkey_switches = 0ULL;
|
||||
|
||||
static clks_bool clks_keyboard_queue_push(char ch) {
|
||||
if (clks_kbd_input_count >= CLKS_KBD_INPUT_CAP) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_kbd_input_queue[clks_kbd_input_head] = ch;
|
||||
clks_kbd_input_head = (u16)((clks_kbd_input_head + 1U) % CLKS_KBD_INPUT_CAP);
|
||||
clks_kbd_input_count++;
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static char clks_keyboard_translate_scancode(u8 code) {
|
||||
clks_bool shift_active = (clks_kbd_lshift_down == CLKS_TRUE || clks_kbd_rshift_down == CLKS_TRUE)
|
||||
? CLKS_TRUE
|
||||
: CLKS_FALSE;
|
||||
|
||||
if (shift_active == CLKS_TRUE) {
|
||||
return clks_kbd_shift_map[code];
|
||||
}
|
||||
|
||||
return clks_kbd_map[code];
|
||||
}
|
||||
|
||||
void clks_keyboard_init(void) {
|
||||
clks_kbd_input_head = 0U;
|
||||
clks_kbd_input_tail = 0U;
|
||||
clks_kbd_input_count = 0U;
|
||||
clks_kbd_alt_down = CLKS_FALSE;
|
||||
clks_kbd_lshift_down = CLKS_FALSE;
|
||||
clks_kbd_rshift_down = CLKS_FALSE;
|
||||
clks_kbd_e0_prefix = CLKS_FALSE;
|
||||
clks_kbd_hotkey_switches = 0ULL;
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "KBD", "ALT+F1..F4 TTY HOTKEY ONLINE");
|
||||
clks_log(CLKS_LOG_INFO, "KBD", "PS2 INPUT QUEUE ONLINE");
|
||||
}
|
||||
|
||||
void clks_keyboard_handle_scancode(u8 scancode) {
|
||||
clks_bool released = ((scancode & 0x80U) != 0U) ? CLKS_TRUE : CLKS_FALSE;
|
||||
u8 code = (u8)(scancode & 0x7FU);
|
||||
clks_bool released;
|
||||
u8 code;
|
||||
|
||||
if (scancode == CLKS_SC_EXT_PREFIX) {
|
||||
clks_kbd_e0_prefix = CLKS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
released = ((scancode & 0x80U) != 0U) ? CLKS_TRUE : CLKS_FALSE;
|
||||
code = (u8)(scancode & 0x7FU);
|
||||
|
||||
if (code == CLKS_SC_ALT) {
|
||||
clks_kbd_alt_down = (released == CLKS_FALSE) ? CLKS_TRUE : CLKS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (released == CLKS_TRUE || clks_kbd_alt_down == CLKS_FALSE) {
|
||||
if (code == CLKS_SC_LSHIFT) {
|
||||
clks_kbd_lshift_down = (released == CLKS_FALSE) ? CLKS_TRUE : CLKS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code >= CLKS_SC_F1 && code <= CLKS_SC_F4) {
|
||||
if (code == CLKS_SC_RSHIFT) {
|
||||
clks_kbd_rshift_down = (released == CLKS_FALSE) ? CLKS_TRUE : CLKS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (released == CLKS_TRUE) {
|
||||
if (clks_kbd_e0_prefix == CLKS_TRUE) {
|
||||
clks_kbd_e0_prefix = CLKS_FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_kbd_e0_prefix == CLKS_TRUE) {
|
||||
clks_kbd_e0_prefix = CLKS_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_kbd_alt_down == CLKS_TRUE && code >= CLKS_SC_F1 && code <= CLKS_SC_F4) {
|
||||
u32 target = (u32)(code - CLKS_SC_F1);
|
||||
u32 before = clks_tty_active();
|
||||
u32 after;
|
||||
@@ -45,9 +137,34 @@ void clks_keyboard_handle_scancode(u8 scancode) {
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)after);
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "HOTKEY_SWITCHES", clks_kbd_hotkey_switches);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
char translated = clks_keyboard_translate_scancode(code);
|
||||
|
||||
if (translated != '\0') {
|
||||
(void)clks_keyboard_queue_push(translated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 clks_keyboard_hotkey_switch_count(void) {
|
||||
return clks_kbd_hotkey_switches;
|
||||
}
|
||||
|
||||
clks_bool clks_keyboard_pop_char(char *out_ch) {
|
||||
if (out_ch == CLKS_NULL || clks_kbd_input_count == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
*out_ch = clks_kbd_input_queue[clks_kbd_input_tail];
|
||||
clks_kbd_input_tail = (u16)((clks_kbd_input_tail + 1U) % CLKS_KBD_INPUT_CAP);
|
||||
clks_kbd_input_count--;
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
u64 clks_keyboard_buffered_count(void) {
|
||||
return (u64)clks_kbd_input_count;
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <clks/scheduler.h>
|
||||
#include <clks/serial.h>
|
||||
#include <clks/service.h>
|
||||
#include <clks/shell.h>
|
||||
#include <clks/syscall.h>
|
||||
#include <clks/tty.h>
|
||||
#include <clks/types.h>
|
||||
@@ -62,90 +63,9 @@ static void clks_task_kelfd(u64 tick) {
|
||||
static void clks_task_usrd(u64 tick) {
|
||||
clks_service_heartbeat(CLKS_SERVICE_USER, tick);
|
||||
clks_userland_tick(tick);
|
||||
clks_shell_tick(tick);
|
||||
}
|
||||
|
||||
static void clks_stage15_syscall_probe(void) {
|
||||
char child_name[96];
|
||||
char read_buf[160];
|
||||
u64 root_children;
|
||||
u64 got_name;
|
||||
u64 read_len;
|
||||
u64 run_status;
|
||||
|
||||
root_children = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_CHILD_COUNT, (u64)"/", 0ULL, 0ULL);
|
||||
clks_log_hex(CLKS_LOG_INFO, "SHELL", "ROOT_CHILDREN", root_children);
|
||||
|
||||
child_name[0] = '\0';
|
||||
got_name = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_GET_CHILD_NAME, (u64)"/", 0ULL, (u64)child_name);
|
||||
|
||||
if (got_name == 1ULL) {
|
||||
child_name[sizeof(child_name) - 1U] = '\0';
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "ROOT_ENTRY0");
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", child_name);
|
||||
}
|
||||
|
||||
read_len = clks_syscall_invoke_kernel(CLKS_SYSCALL_FS_READ,
|
||||
(u64)"/README.txt",
|
||||
(u64)read_buf,
|
||||
(u64)(sizeof(read_buf) - 1U));
|
||||
|
||||
if (read_len > 0ULL && read_len != (u64)-1) {
|
||||
if (read_len >= (u64)sizeof(read_buf)) {
|
||||
read_len = (u64)sizeof(read_buf) - 1ULL;
|
||||
}
|
||||
|
||||
read_buf[read_len] = '\0';
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "README PREVIEW");
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", read_buf);
|
||||
}
|
||||
|
||||
run_status = clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_PATH, (u64)"/system/elfrunner.elf", 0ULL, 0ULL);
|
||||
|
||||
if (run_status == 0ULL) {
|
||||
clks_log(CLKS_LOG_INFO, "EXEC", "RUN /SYSTEM/ELFRUNNER.ELF OK");
|
||||
} else {
|
||||
clks_log(CLKS_LOG_WARN, "EXEC", "RUN /SYSTEM/ELFRUNNER.ELF FAILED");
|
||||
}
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"EXEC",
|
||||
"REQUESTS",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_REQUESTS, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"EXEC",
|
||||
"SUCCESS",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_EXEC_SUCCESS, 0ULL, 0ULL, 0ULL));
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"USER",
|
||||
"SHELL_READY",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_USER_SHELL_READY, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"USER",
|
||||
"EXEC_REQUESTED",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_USER_EXEC_REQUESTED, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"USER",
|
||||
"LAUNCH_TRIES",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_USER_LAUNCH_TRIES, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"USER",
|
||||
"LAUNCH_OK",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_USER_LAUNCH_OK, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"USER",
|
||||
"LAUNCH_FAIL",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_USER_LAUNCH_FAIL, 0ULL, 0ULL, 0ULL));
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"TTY",
|
||||
"COUNT",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_TTY_COUNT, 0ULL, 0ULL, 0ULL));
|
||||
clks_log_hex(CLKS_LOG_INFO,
|
||||
"TTY",
|
||||
"ACTIVE",
|
||||
clks_syscall_invoke_kernel(CLKS_SYSCALL_TTY_ACTIVE, 0ULL, 0ULL, 0ULL));
|
||||
}
|
||||
void clks_kernel_main(void) {
|
||||
const struct limine_framebuffer *boot_fb;
|
||||
const struct limine_memmap_response *boot_memmap;
|
||||
@@ -171,7 +91,7 @@ void clks_kernel_main(void) {
|
||||
clks_tty_init();
|
||||
}
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE15 START");
|
||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE16 START");
|
||||
|
||||
if (boot_fb == CLKS_NULL) {
|
||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||
@@ -281,10 +201,12 @@ void clks_kernel_main(void) {
|
||||
syscall_ticks = clks_syscall_invoke_kernel(CLKS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
||||
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
|
||||
|
||||
clks_stage15_syscall_probe();
|
||||
clks_shell_init();
|
||||
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "COUNT", (u64)clks_tty_count());
|
||||
clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)clks_tty_active());
|
||||
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
|
||||
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
|
||||
|
||||
clks_cpu_halt_forever();
|
||||
}
|
||||
}
|
||||
441
clks/kernel/shell.c
Normal file
441
clks/kernel/shell.c
Normal file
@@ -0,0 +1,441 @@
|
||||
#include <clks/exec.h>
|
||||
#include <clks/fs.h>
|
||||
#include <clks/keyboard.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/shell.h>
|
||||
#include <clks/string.h>
|
||||
#include <clks/tty.h>
|
||||
#include <clks/types.h>
|
||||
|
||||
#define CLKS_SHELL_LINE_MAX 192U
|
||||
#define CLKS_SHELL_CMD_MAX 32U
|
||||
#define CLKS_SHELL_ARG_MAX 160U
|
||||
#define CLKS_SHELL_NAME_MAX 96U
|
||||
#define CLKS_SHELL_PATH_MAX 192U
|
||||
#define CLKS_SHELL_CAT_LIMIT 512U
|
||||
#define CLKS_SHELL_INPUT_BUDGET 32U
|
||||
#define CLKS_SHELL_CLEAR_LINES 56U
|
||||
|
||||
static clks_bool clks_shell_ready = CLKS_FALSE;
|
||||
static char clks_shell_line[CLKS_SHELL_LINE_MAX];
|
||||
static usize clks_shell_line_len = 0U;
|
||||
|
||||
static clks_bool clks_shell_is_space(char ch) {
|
||||
return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_is_printable(char ch) {
|
||||
return (ch >= 32 && ch <= 126) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_streq(const char *left, const char *right) {
|
||||
return (clks_strcmp(left, right) == 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static void clks_shell_write(const char *text) {
|
||||
if (text == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
clks_tty_write(text);
|
||||
}
|
||||
|
||||
static void clks_shell_write_char(char ch) {
|
||||
clks_tty_write_char(ch);
|
||||
}
|
||||
|
||||
static void clks_shell_writeln(const char *text) {
|
||||
clks_shell_write(text);
|
||||
clks_shell_write_char('\n');
|
||||
}
|
||||
|
||||
static void clks_shell_prompt(void) {
|
||||
clks_shell_write("cleonos> ");
|
||||
}
|
||||
|
||||
static void clks_shell_reset_line(void) {
|
||||
clks_shell_line_len = 0U;
|
||||
clks_shell_line[0] = '\0';
|
||||
}
|
||||
|
||||
static void clks_shell_trim(char *line) {
|
||||
usize start = 0U;
|
||||
usize i = 0U;
|
||||
usize len;
|
||||
|
||||
if (line == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (line[start] != '\0' && clks_shell_is_space(line[start]) == CLKS_TRUE) {
|
||||
start++;
|
||||
}
|
||||
|
||||
if (start > 0U) {
|
||||
while (line[start + i] != '\0') {
|
||||
line[i] = line[start + i];
|
||||
i++;
|
||||
}
|
||||
|
||||
line[i] = '\0';
|
||||
}
|
||||
|
||||
len = clks_strlen(line);
|
||||
|
||||
while (len > 0U && clks_shell_is_space(line[len - 1U]) == CLKS_TRUE) {
|
||||
line[len - 1U] = '\0';
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_split_line(const char *line,
|
||||
char *out_cmd,
|
||||
usize out_cmd_size,
|
||||
char *out_arg,
|
||||
usize out_arg_size) {
|
||||
usize i = 0U;
|
||||
usize cmd_pos = 0U;
|
||||
usize arg_pos = 0U;
|
||||
|
||||
if (line == CLKS_NULL || out_cmd == CLKS_NULL || out_arg == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
out_cmd[0] = '\0';
|
||||
out_arg[0] = '\0';
|
||||
|
||||
while (line[i] != '\0' && clks_shell_is_space(line[i]) == CLKS_TRUE) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (line[i] != '\0' && clks_shell_is_space(line[i]) == CLKS_FALSE) {
|
||||
if (cmd_pos + 1U < out_cmd_size) {
|
||||
out_cmd[cmd_pos++] = line[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out_cmd[cmd_pos] = '\0';
|
||||
|
||||
while (line[i] != '\0' && clks_shell_is_space(line[i]) == CLKS_TRUE) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (line[i] != '\0') {
|
||||
if (arg_pos + 1U < out_arg_size) {
|
||||
out_arg[arg_pos++] = line[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
out_arg[arg_pos] = '\0';
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_has_suffix(const char *name, const char *suffix) {
|
||||
usize name_len;
|
||||
usize suffix_len;
|
||||
|
||||
if (name == CLKS_NULL || suffix == CLKS_NULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
name_len = clks_strlen(name);
|
||||
suffix_len = clks_strlen(suffix);
|
||||
|
||||
if (suffix_len > name_len) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
return (clks_strcmp(name + (name_len - suffix_len), suffix) == 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
}
|
||||
|
||||
static clks_bool clks_shell_resolve_exec_path(const char *arg, char *out_path, usize out_path_size) {
|
||||
usize cursor = 0U;
|
||||
usize i;
|
||||
|
||||
if (arg == CLKS_NULL || out_path == CLKS_NULL || out_path_size == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (arg[0] == '\0') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
out_path[0] = '\0';
|
||||
|
||||
if (arg[0] == '/') {
|
||||
usize len = clks_strlen(arg);
|
||||
if (len + 1U > out_path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
clks_memcpy(out_path, arg, len + 1U);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
{
|
||||
static const char shell_prefix[] = "/shell/";
|
||||
usize prefix_len = (sizeof(shell_prefix) - 1U);
|
||||
|
||||
if (prefix_len + 1U >= out_path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memcpy(out_path, shell_prefix, prefix_len);
|
||||
cursor = prefix_len;
|
||||
}
|
||||
|
||||
for (i = 0U; arg[i] != '\0'; i++) {
|
||||
if (cursor + 1U >= out_path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
out_path[cursor++] = arg[i];
|
||||
}
|
||||
|
||||
out_path[cursor] = '\0';
|
||||
|
||||
if (clks_shell_has_suffix(out_path, ".elf") == CLKS_FALSE) {
|
||||
static const char elf_suffix[] = ".elf";
|
||||
usize suffix_len = (sizeof(elf_suffix) - 1U);
|
||||
|
||||
if (cursor + suffix_len + 1U > out_path_size) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_memcpy(out_path + cursor, elf_suffix, suffix_len + 1U);
|
||||
}
|
||||
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_help(void) {
|
||||
clks_shell_writeln("commands:");
|
||||
clks_shell_writeln(" help");
|
||||
clks_shell_writeln(" ls [dir]");
|
||||
clks_shell_writeln(" cat <file>");
|
||||
clks_shell_writeln(" exec <path|name>");
|
||||
clks_shell_writeln(" clear");
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_ls(const char *arg) {
|
||||
struct clks_fs_node_info info;
|
||||
const char *path = arg;
|
||||
u64 count;
|
||||
u64 i;
|
||||
|
||||
if (path == CLKS_NULL || path[0] == '\0') {
|
||||
path = "/";
|
||||
}
|
||||
|
||||
if (clks_fs_stat(path, &info) == CLKS_FALSE || info.type != CLKS_FS_NODE_DIR) {
|
||||
clks_shell_writeln("ls: directory not found");
|
||||
return;
|
||||
}
|
||||
|
||||
count = clks_fs_count_children(path);
|
||||
|
||||
if (count == 0ULL) {
|
||||
clks_shell_writeln("(empty)");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0ULL; i < count; i++) {
|
||||
char name[CLKS_SHELL_NAME_MAX];
|
||||
|
||||
name[0] = '\0';
|
||||
if (clks_fs_get_child_name(path, i, name, sizeof(name)) == CLKS_FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clks_shell_writeln(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_cat(const char *arg) {
|
||||
const void *data;
|
||||
u64 size = 0ULL;
|
||||
u64 copy_len;
|
||||
char out[CLKS_SHELL_CAT_LIMIT + 1U];
|
||||
|
||||
if (arg == CLKS_NULL || arg[0] == '\0') {
|
||||
clks_shell_writeln("cat: file path required");
|
||||
return;
|
||||
}
|
||||
|
||||
data = clks_fs_read_all(arg, &size);
|
||||
|
||||
if (data == CLKS_NULL) {
|
||||
clks_shell_writeln("cat: file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0ULL) {
|
||||
clks_shell_writeln("(empty file)");
|
||||
return;
|
||||
}
|
||||
|
||||
copy_len = (size < CLKS_SHELL_CAT_LIMIT) ? size : CLKS_SHELL_CAT_LIMIT;
|
||||
clks_memcpy(out, data, (usize)copy_len);
|
||||
out[copy_len] = '\0';
|
||||
|
||||
clks_shell_writeln(out);
|
||||
|
||||
if (size > copy_len) {
|
||||
clks_shell_writeln("[cat] output truncated");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_exec(const char *arg) {
|
||||
char path[CLKS_SHELL_PATH_MAX];
|
||||
u64 status = (u64)-1;
|
||||
|
||||
if (clks_shell_resolve_exec_path(arg, path, sizeof(path)) == CLKS_FALSE) {
|
||||
clks_shell_writeln("exec: invalid target");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_exec_run_path(path, &status) == CLKS_TRUE && status == 0ULL) {
|
||||
clks_shell_writeln("exec: request accepted");
|
||||
} else {
|
||||
clks_shell_writeln("exec: request failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_cmd_clear(void) {
|
||||
u32 i;
|
||||
|
||||
for (i = 0U; i < CLKS_SHELL_CLEAR_LINES; i++) {
|
||||
clks_shell_write_char('\n');
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_shell_execute_line(const char *line) {
|
||||
char line_buf[CLKS_SHELL_LINE_MAX];
|
||||
char cmd[CLKS_SHELL_CMD_MAX];
|
||||
char arg[CLKS_SHELL_ARG_MAX];
|
||||
usize i = 0U;
|
||||
|
||||
if (line == CLKS_NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (line[i] != '\0' && i + 1U < sizeof(line_buf)) {
|
||||
line_buf[i] = line[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
line_buf[i] = '\0';
|
||||
clks_shell_trim(line_buf);
|
||||
|
||||
if (line_buf[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
clks_shell_split_line(line_buf, cmd, sizeof(cmd), arg, sizeof(arg));
|
||||
|
||||
if (clks_shell_streq(cmd, "help") == CLKS_TRUE) {
|
||||
clks_shell_cmd_help();
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "ls") == CLKS_TRUE) {
|
||||
clks_shell_cmd_ls(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "cat") == CLKS_TRUE) {
|
||||
clks_shell_cmd_cat(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "exec") == CLKS_TRUE || clks_shell_streq(cmd, "run") == CLKS_TRUE) {
|
||||
clks_shell_cmd_exec(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_streq(cmd, "clear") == CLKS_TRUE) {
|
||||
clks_shell_cmd_clear();
|
||||
return;
|
||||
}
|
||||
|
||||
clks_shell_writeln("unknown command; type 'help'");
|
||||
}
|
||||
|
||||
static void clks_shell_handle_char(char ch) {
|
||||
if (ch == '\r') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\n') {
|
||||
clks_shell_write_char('\n');
|
||||
clks_shell_line[clks_shell_line_len] = '\0';
|
||||
clks_shell_execute_line(clks_shell_line);
|
||||
clks_shell_reset_line();
|
||||
clks_shell_prompt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\b' || ch == 127) {
|
||||
if (clks_shell_line_len > 0U) {
|
||||
clks_shell_line_len--;
|
||||
clks_shell_line[clks_shell_line_len] = '\0';
|
||||
clks_shell_write_char('\b');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\t') {
|
||||
ch = ' ';
|
||||
}
|
||||
|
||||
if (clks_shell_is_printable(ch) == CLKS_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_shell_line_len + 1U >= CLKS_SHELL_LINE_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
clks_shell_line[clks_shell_line_len++] = ch;
|
||||
clks_shell_line[clks_shell_line_len] = '\0';
|
||||
clks_shell_write_char(ch);
|
||||
}
|
||||
|
||||
void clks_shell_init(void) {
|
||||
clks_shell_reset_line();
|
||||
|
||||
if (clks_tty_ready() == CLKS_FALSE) {
|
||||
clks_shell_ready = CLKS_FALSE;
|
||||
clks_log(CLKS_LOG_WARN, "SHELL", "TTY NOT READY; SHELL DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
clks_shell_ready = CLKS_TRUE;
|
||||
|
||||
clks_shell_writeln("");
|
||||
clks_shell_writeln("CLeonOS interactive shell ready");
|
||||
clks_shell_writeln("type 'help' for commands");
|
||||
clks_shell_prompt();
|
||||
|
||||
clks_log(CLKS_LOG_INFO, "SHELL", "INTERACTIVE LOOP ONLINE");
|
||||
}
|
||||
|
||||
void clks_shell_tick(u64 tick) {
|
||||
u32 budget = 0U;
|
||||
char ch;
|
||||
|
||||
(void)tick;
|
||||
|
||||
if (clks_shell_ready == CLKS_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (budget < CLKS_SHELL_INPUT_BUDGET) {
|
||||
if (clks_keyboard_pop_char(&ch) == CLKS_FALSE) {
|
||||
break;
|
||||
}
|
||||
|
||||
clks_shell_handle_char(ch);
|
||||
budget++;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <clks/fs.h>
|
||||
#include <clks/interrupts.h>
|
||||
#include <clks/kelf.h>
|
||||
#include <clks/keyboard.h>
|
||||
#include <clks/log.h>
|
||||
#include <clks/scheduler.h>
|
||||
#include <clks/service.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#define CLKS_SYSCALL_LOG_MAX_LEN 191U
|
||||
#define CLKS_SYSCALL_PATH_MAX 192U
|
||||
#define CLKS_SYSCALL_NAME_MAX 96U
|
||||
#define CLKS_SYSCALL_IO_MAX_LEN 512U
|
||||
|
||||
struct clks_syscall_frame {
|
||||
u64 rax;
|
||||
@@ -89,6 +91,44 @@ static u64 clks_syscall_log_write(u64 arg0, u64 arg1) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_tty_write(u64 arg0, u64 arg1) {
|
||||
const char *src = (const char *)arg0;
|
||||
u64 len = arg1;
|
||||
char buf[CLKS_SYSCALL_IO_MAX_LEN + 1U];
|
||||
u64 i;
|
||||
|
||||
if (src == CLKS_NULL || len == 0ULL) {
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
if (len > CLKS_SYSCALL_IO_MAX_LEN) {
|
||||
len = CLKS_SYSCALL_IO_MAX_LEN;
|
||||
}
|
||||
|
||||
for (i = 0ULL; i < len; i++) {
|
||||
buf[i] = src[i];
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
clks_tty_write(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_tty_write_char(u64 arg0) {
|
||||
clks_tty_write_char((char)(arg0 & 0xFFULL));
|
||||
return 1ULL;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_kbd_get_char(void) {
|
||||
char ch;
|
||||
|
||||
if (clks_keyboard_pop_char(&ch) == CLKS_FALSE) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
return (u64)(u8)ch;
|
||||
}
|
||||
|
||||
static u64 clks_syscall_fs_child_count(u64 arg0) {
|
||||
char path[CLKS_SYSCALL_PATH_MAX];
|
||||
|
||||
@@ -228,6 +268,12 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
||||
case CLKS_SYSCALL_TTY_SWITCH:
|
||||
clks_tty_switch((u32)frame->rbx);
|
||||
return (u64)clks_tty_active();
|
||||
case CLKS_SYSCALL_TTY_WRITE:
|
||||
return clks_syscall_tty_write(frame->rbx, frame->rcx);
|
||||
case CLKS_SYSCALL_TTY_WRITE_CHAR:
|
||||
return clks_syscall_tty_write_char(frame->rbx);
|
||||
case CLKS_SYSCALL_KBD_GET_CHAR:
|
||||
return clks_syscall_kbd_get_char();
|
||||
default:
|
||||
return (u64)-1;
|
||||
}
|
||||
@@ -244,5 +290,4 @@ u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -141,6 +141,24 @@ void clks_tty_write_char(char ch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\b') {
|
||||
if (col == 0U && row == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (col == 0U) {
|
||||
row--;
|
||||
col = clks_tty_cols - 1U;
|
||||
} else {
|
||||
col--;
|
||||
}
|
||||
|
||||
clks_tty_put_visible(tty_index, row, col, ' ');
|
||||
clks_tty_cursor_row[tty_index] = row;
|
||||
clks_tty_cursor_col[tty_index] = col;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\t') {
|
||||
clks_tty_write_char(' ');
|
||||
clks_tty_write_char(' ');
|
||||
|
||||
Reference in New Issue
Block a user