From fb3e073565c416a6d663107cf02a7245a12577e6 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 20 Jan 2026 17:09:58 -0700 Subject: [PATCH] use raw mode for linux so that I can later implement history and such. also update msh_read_input doc because i think it's gonna return more stuff soon --- src/builtins/builtins.c | 6 +++ src/lexer/lexer.c | 2 +- src/main.c | 6 ++- src/system/linux/linux.c | 90 ++++++++++++++++++++++++++++++++++------ src/system/linux/linux.h | 3 ++ src/system/system.h | 5 ++- 6 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/builtins/builtins.c b/src/builtins/builtins.c index b68144d..e11547c 100644 --- a/src/builtins/builtins.c +++ b/src/builtins/builtins.c @@ -4,18 +4,24 @@ int hashes_calced = 0; int cd_hash = 0; +int exit_hash = 0; int msh_try_builtin(char *cmd, char **args) { int hash = str_hash(cmd); if (hashes_calced == 0) { cd_hash = str_hash("cd"); + exit_hash = str_hash("exit"); hashes_calced = 1; } if (hash == cd_hash) { msh_builtin_cd(args[1]); return 1; } + if (hash == exit_hash) { + msh_exit_shell(); + return 0; + } return 0; }; diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 374cd95..1c41b35 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -181,7 +181,7 @@ void msh_lexer_execute(msh_lexer *lexer) { msh_deallocate(full_path); } if (!exec_success) { - msh_print_strings("msh: ", cmd, ": command not found\n", 0); + msh_print_strings("msh: ", cmd, ": command not found\n\r", 0); } msh_deallocate(args); diff --git a/src/main.c b/src/main.c index 4b89775..3c4bc8d 100644 --- a/src/main.c +++ b/src/main.c @@ -20,8 +20,10 @@ MSH_ENTRY_POINT { while ((out = msh_read_input(buf, &sz, 2048)), !out) { } - msh_lexer_parse(lexer, buf, sz + 1); - msh_lexer_execute(lexer); + if (*buf != '\0') { + msh_lexer_parse(lexer, buf, sz + 1); + msh_lexer_execute(lexer); + } // msh_execute(buf, args); diff --git a/src/system/linux/linux.c b/src/system/linux/linux.c index 5c9537f..c231f95 100644 --- a/src/system/linux/linux.c +++ b/src/system/linux/linux.c @@ -2,27 +2,54 @@ #include "../system.h" #include "syscall.h" +#include #include #include +#include +#include #include +#include #include +#include + char msh_path_seperator = '/'; int msh_read_input(char *ptr, SIZE_TYPE *size, SIZE_TYPE n) { - char ch; - SIZE_TYPE sz; + char ch = 0; + SIZE_TYPE sz = 0; + while (ch == 0) { + sz = (SIZE_TYPE)SYSCALL(read, 0, &ch, 1); + /* don't write control characters or add them to the buffer */ + if (ch >= 0x20 && ch <= 0x7E) { + ptr[*size] = ch; + SYSCALL(write, 1, &ch, 1); + *size += sz; + } else { + switch (ch) { + /* return */ + case '\r': + ptr[*size] = '\0'; + SYSCALL(write, 1, "\n\r", 2); + return 1; + break; + /* backspace */ + case '\177': + if (*size <= 0) { + return 0; + } + + SYSCALL(write, 1, "\33[D \33[D", 7); + *size -= 1; + break; + } + } + } + if (*size >= n) { return 2; } - sz = (SIZE_TYPE)SYSCALL(read, 0, &ch, 1); - if (ch == '\n') { - *(ptr + *size) = '\0'; - return 1; - } else { - *(ptr + *size) = ch; - *size += sz; - } + return 0; }; @@ -76,12 +103,18 @@ int msh_execute(char *cmd, char **args) { siginfo_t info; SYSCALL(waitid, P_ALL, 0, &info, WEXITED); SYSCALL(kill, fork, SIGKILL); + + SYSCALL(write, 1, "\r", 2); + return info.si_code; } return 0; }; -void msh_exit_shell() { SYSCALL(exit, 0); }; +void msh_exit_shell() { + msh_backend_deinit(); + SYSCALL(exit, 0); +}; msh_file *msh_file_open(const char *file) { msh_file *f = msh_allocate(sizeof(struct msh_file_t)); @@ -139,6 +172,37 @@ int msh_path_is_directory(char *path) { return S_ISDIR(path_stat.st_mode); }; -void msh_backend_init() { msh_linux_env_map_init(); }; +static struct termios kbmode_og; +static struct termios ttsmode_og; +static struct termios ttsmode; -void msh_backend_deinit() { msh_linux_env_map_deinit(); }; +void msh_linux_start_input_capture() { + SYSCALL(ioctl, 0, KDGKBMODE, &kbmode_og); + SYSCALL(ioctl, 0, TCGETS, &ttsmode_og); + SYSCALL(ioctl, 0, TCGETS, &ttsmode); + + ttsmode.c_iflag &= + ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + ttsmode.c_oflag &= ~OPOST; + ttsmode.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ttsmode.c_cflag &= ~(CSIZE | PARENB); + ttsmode.c_cflag |= CS8; + + SYSCALL(ioctl, 0, TCSETSW, &ttsmode); + + SYSCALL(ioctl, 0, KDSKBMODE, K_RAW); +}; +void msh_linux_end_input_capture() { + SYSCALL(ioctl, 0, TCSETSW, &ttsmode_og); + SYSCALL(ioctl, 0, KDSKBMODE, &kbmode_og); +}; + +void msh_backend_init() { + msh_linux_env_map_init(); + msh_linux_start_input_capture(); +}; + +void msh_backend_deinit() { + msh_linux_env_map_deinit(); + msh_linux_end_input_capture(); +}; diff --git a/src/system/linux/linux.h b/src/system/linux/linux.h index 7d1f92a..a12233a 100644 --- a/src/system/linux/linux.h +++ b/src/system/linux/linux.h @@ -8,6 +8,9 @@ void msh_linux_print_errno(int errno); void msh_linux_env_map_init(); void msh_linux_env_map_deinit(); +void msh_linux_start_input_capture(); +void msh_linux_end_input_capture(); + struct msh_file_t { int fd; }; diff --git a/src/system/system.h b/src/system/system.h index 96bf755..803c3bb 100644 --- a/src/system/system.h +++ b/src/system/system.h @@ -59,7 +59,10 @@ void msh_file_read(msh_file *file, char *ptr, SIZE_TYPE n); /* * Read user input into ptr, stopping if it has reached n characters. - * returns 1 if finished reading, 2 if it ran out of space. + * Also responsible for handling backspace. + * RETURNS: + * - 1 if finished reading + * - 2 if it ran out of space. */ int msh_read_input(char *ptr, SIZE_TYPE *size, SIZE_TYPE n);