From e0a751eec3bf68433b7bacfb1ef237bc913cb23b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 19 Jan 2026 17:12:32 -0700 Subject: [PATCH] environment passthrough --- src/lexer/lexer.c | 1 + src/main.c | 2 +- src/system/linux/env.c | 111 +++++++++++++++++++++++++-------------- src/system/linux/linux.c | 45 ++++++++++++++-- src/system/linux/linux.h | 12 +++++ src/system/system.h | 8 +-- src/util/string.c | 24 +++++++++ src/util/util.h | 7 +++ 8 files changed, 164 insertions(+), 46 deletions(-) diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index e310f88..69b4d66 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -171,6 +171,7 @@ void msh_lexer_execute(msh_lexer *lexer) { } j++; } + msh_deallocate(full_path); } if (!exec_success) { msh_print_strings("msh: ", cmd, ": command not found\n", 0); diff --git a/src/main.c b/src/main.c index e14356e..4b89775 100644 --- a/src/main.c +++ b/src/main.c @@ -15,7 +15,7 @@ MSH_ENTRY_POINT { int i = 0, n = 0, last = 0; unsigned long long sz = 0; - msh_print_strings(msh_working_directory(), " >", 0); + msh_print_strings(msh_working_directory(), " %> ", 0); while ((out = msh_read_input(buf, &sz, 2048)), !out) { } diff --git a/src/system/linux/env.c b/src/system/linux/env.c index 676c6e9..22c072c 100644 --- a/src/system/linux/env.c +++ b/src/system/linux/env.c @@ -1,29 +1,20 @@ #include "../system.h" #include "linux.h" -#include "syscall.h" -typedef struct msh_linux_env_item_t msh_linux_env_item; -struct msh_linux_env_item_t { - unsigned long key; - char *value; - int is_path; - msh_linux_env_item *next; -}; - -static msh_linux_env_item *env_items = 0; +msh_linux_env_item *env_items = 0; +msh_linux_env_item *env_item_tail = 0; void msh_linux_env_map_init() { msh_file *env_file; - SIZE_TYPE file_size; + SIZE_TYPE cur; char *file_buf; char ch = 1; int counter = 0, i = 0; - msh_linux_env_item *env_item_cur; if (!env_items) { env_items = msh_callocate(1, sizeof(msh_linux_env_item)); } - env_item_cur = env_items; + env_item_tail = env_items; env_file = msh_file_open("/proc/self/environ"); file_buf = msh_callocate(512, sizeof(char)); @@ -31,35 +22,39 @@ void msh_linux_env_map_init() { while (1) { msh_file_read(env_file, &ch, 1); - if (ch == ':' && env_item_cur->is_path == 1) { - file_buf[file_size++] = '\0'; + if (ch == ':' && env_item_tail->is_path == 1) { + file_buf[cur++] = '\0'; } else if (ch != '=') { - file_buf[file_size++] = ch; + file_buf[cur++] = ch; } else { - file_buf[file_size++] = '\0'; + file_buf[cur++] = '\0'; } if (ch == '=') { - env_item_cur->key = str_hash(file_buf); - if (env_item_cur->key == str_hash("PATH")) { - env_item_cur->is_path = 1; + env_item_tail->key = msh_allocate(cur); + msh_str_copy_str(env_item_tail->key, file_buf); + env_item_tail->key_len = cur; + env_item_tail->key_hash = str_hash(file_buf); + if (env_item_tail->key_hash == str_hash("PATH")) { + env_item_tail->is_path = 1; } - for (i = 0; i < file_size; i++) { + for (i = 0; i < cur; i++) { file_buf[i] = 0; } - file_size = 0; + cur = 0; } else if (ch == '\0') { - env_item_cur->value = file_buf; - env_item_cur->next = msh_callocate(1, sizeof(msh_linux_env_item)); + env_item_tail->value = file_buf; + env_item_tail->value_len = cur; + env_item_tail->next = msh_callocate(1, sizeof(msh_linux_env_item)); /* double null for path variables */ - if (env_item_cur->is_path) { - file_buf[file_size++] = '\0'; + if (env_item_tail->is_path) { + file_buf[cur++] = '\0'; } file_buf = msh_callocate(512, sizeof(char)); - file_size = 0; - env_item_cur = env_item_cur->next; + cur = 0; + env_item_tail = env_item_tail->next; counter++; @@ -78,28 +73,68 @@ void msh_linux_env_map_init() { void msh_linux_env_map_deinit() {}; const char *msh_env_get(const char *key) { - msh_linux_env_item *env_item_cur = env_items; + msh_linux_env_item *env_item_tail = env_items; int hash = str_hash((char *)key); - while (env_item_cur->next != 0) { - if (env_item_cur->key == hash) { - return env_item_cur->value; + while (env_item_tail->next != 0) { + if (env_item_tail->key_hash == hash) { + return env_item_tail->value; } - env_item_cur = env_item_cur->next; + env_item_tail = env_item_tail->next; } return 0; }; const char *msh_env_get_path() { - msh_linux_env_item *env_item_cur = env_items; + msh_linux_env_item *env_item_tail = env_items; - while (env_item_cur->next != 0) { - if (env_item_cur->is_path) { - return env_item_cur->value; + while (env_item_tail->next != 0) { + if (env_item_tail->is_path) { + return env_item_tail->value; } - env_item_cur = env_item_cur->next; + env_item_tail = env_item_tail->next; } return 0; }; + +void msh_env_set(const char *key, char *value) { + int hash = str_hash((char *)key); + int env_was_set = 0; + int key_size = 0, value_size = 0; + msh_linux_env_item *env_item_local_cur = env_items; + char ch = value[0]; + + while (ch != '\0') { + ch = value[++value_size]; + } + + while (env_item_local_cur == 0) { + if (env_item_local_cur->key_hash == hash) { + msh_exit_shell(); + env_item_local_cur->value = value; + env_item_local_cur->value_len = value_size; + env_was_set = 1; + break; + } + env_item_local_cur = env_item_local_cur->next; + } + if (env_was_set == 0) { + ch = key[0]; + + while (ch != '\0') { + ch = key[++key_size]; + } + + env_item_tail->next = msh_allocate(sizeof(msh_linux_env_item)); + + env_item_tail->next->key = (char *)key; + env_item_tail->next->key_hash = hash; + env_item_tail->next->key_len = key_size; + env_item_tail->next->value = value; + env_item_tail->next->value_len = value_size; + + env_item_tail = env_item_tail->next; + } +}; diff --git a/src/system/linux/linux.c b/src/system/linux/linux.c index a82524f..00a28ab 100644 --- a/src/system/linux/linux.c +++ b/src/system/linux/linux.c @@ -33,12 +33,44 @@ int msh_execute(char *cmd, char **args) { } SIZE_TYPE fork = (SIZE_TYPE)SYSCALL(fork, 0); // int fork = 0; + if (fork == 0) { - int h = (int)SYSCALL(execve, cmd, args, 0); - if (h == -2) { + char **env_translated = 0; + SIZE_TYPE env_translated_size = 0; + int ret, i = 0, n = 0; + msh_linux_env_item *item_list = env_items; + while (item_list->next != 0) { + env_translated_size += 1; + item_list = item_list->next; + } + item_list = env_items; + + env_translated = msh_callocate(env_translated_size + 1, sizeof(char *)); + while (item_list != 0) { + if (item_list->key != 0) { + int n = 0; + char *entry = + msh_allocate(item_list->key_len + item_list->value_len + 2); + msh_str_copy_strs(entry, item_list->key, "=", item_list->value, "\0"); + env_translated[i++] = entry; + } + item_list = item_list->next; + } + + env_translated[i++] = 0; + + ret = (int)SYSCALL(execve, cmd, args, env_translated); + + for (n = 0; n < i; n++) { + msh_deallocate(env_translated[n]); + } + msh_deallocate(env_translated); + + if (ret == -2) { return -1; } - return h; + + return ret; } else { siginfo_t info; SYSCALL(waitid, P_ALL, 0, &info, WEXITED); @@ -96,6 +128,11 @@ void msh_set_working_directory(const char *dir) { SYSCALL(chdir, dir); } int msh_path_exists(char *file) { return SYSCALL(access, file, F_OK) == 0; }; -void msh_backend_init() { msh_linux_env_map_init(); }; +void msh_backend_init() { + msh_linux_env_map_init(); + + msh_env_set("TERMF", "test"); + msh_env_set("TERM", "test"); +}; void msh_backend_deinit() { msh_linux_env_map_deinit(); }; diff --git a/src/system/linux/linux.h b/src/system/linux/linux.h index b272463..7d1f92a 100644 --- a/src/system/linux/linux.h +++ b/src/system/linux/linux.h @@ -12,4 +12,16 @@ struct msh_file_t { int fd; }; +typedef struct msh_linux_env_item_t msh_linux_env_item; +struct msh_linux_env_item_t { + char *key; + unsigned long key_hash; + int key_len; + char *value; + int value_len; + int is_path; + msh_linux_env_item *next; +}; +extern msh_linux_env_item *env_items; + #endif diff --git a/src/system/system.h b/src/system/system.h index 241ca51..842f3c7 100644 --- a/src/system/system.h +++ b/src/system/system.h @@ -18,9 +18,6 @@ void msh_backend_deinit(); /* Allocate memory */ void *msh_allocate(SIZE_TYPE size); -/* Allocates memory for an array of num objects of size */ -void *msh_callocate(SIZE_TYPE number, SIZE_TYPE size); - /* Deallocate memory previously allocated by msh_allocate */ void msh_deallocate(void *ptr); @@ -91,6 +88,11 @@ int msh_execute(char *cmd, char **args); */ const char *msh_env_get(const char *key); +/* + Set the following environment variable. + */ +void msh_env_set(const char *key, char *value); + /* * Gets a NULL-delimited string representing the folders to search for in the * path, ending in two NULLs. diff --git a/src/util/string.c b/src/util/string.c index 2b0fe68..db476df 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -24,3 +24,27 @@ void msh_print_strings(char *str, ...) { msh_print_string(st); } }; + +void msh_str_copy_strs(char *dst, ...) { + int i = 0, n = 0; + va_list va; + + va_start(va, dst); + for (;;) { + char *src = va_arg(va, char *); + if (src == 0) { + break; + } + i = 0; + while ((dst[i + n] = src[i])) { + i++; + } + n += i; + } +}; + +void msh_str_copy_str(char *dst, char *src) { + while ((*dst++ = *src++)) + ; + *dst++ = '\0'; +}; diff --git a/src/util/util.h b/src/util/util.h index 496e670..ef5afbb 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -3,8 +3,15 @@ #include "../system/system.h" +/* Allocates memory for an array of num objects of size */ void *msh_callocate(SIZE_TYPE number, SIZE_TYPE size); +/* Copy src string to dst. */ +void msh_str_copy_str(char *dst, char *src); + +/* Copy NULL terminated array of dst. */ +void msh_str_copy_strs(char *dst, ...); + /* Print NULL terminated array of strings */ void msh_print_strings(char *str, ...);