diff --git a/apps/texed/texed b/apps/texed/texed new file mode 100755 index 0000000..d0ea60a Binary files /dev/null and b/apps/texed/texed differ diff --git a/apps/texed/textbuffer.c b/apps/texed/textbuffer.c index 7f6f2d8..2759dc5 100644 --- a/apps/texed/textbuffer.c +++ b/apps/texed/textbuffer.c @@ -16,7 +16,7 @@ #include #include #else - +#include #include #include #include @@ -618,7 +618,7 @@ int main(int argc, char *argv[]) { } start_color(); - + setlocale(LC_ALL, ""); noecho(); keypad(stdscr, TRUE); #endif // !NCURSES diff --git a/apps/utils/HashMap.hpp b/apps/utils/HashMap.hpp new file mode 100644 index 0000000..96ab1a3 --- /dev/null +++ b/apps/utils/HashMap.hpp @@ -0,0 +1,63 @@ +/* HashMap.hpp */ +#ifndef __HASHMAP_H +#define __HASHMAP_H + +#include + +const size_t HASH_MAP_SIZE = 256; /* Fixed size of the hashmap */ + +/* Entry structure for hashmap */ +struct Entry { + char* key; + char* value; + bool is_occupied; /* Indicates if the entry is occupied */ + + Entry() : key(nullptr), value(nullptr), is_occupied(false) {} +}; + +/* HashMap class */ +class HashMap { +public: + HashMap() { + for (size_t i = 0; i < HASH_MAP_SIZE; ++i) { + entries[i].is_occupied = false; + } + } + + void put(const char* key, const char* value){ + size_t index = hash(key); + entries[index].key = const_cast(key); + entries[index].value = const_cast(value); + entries[index].is_occupied = true; + } + + const char* get(const char* key) { + size_t index = hash(key); + if (entries[index].is_occupied && entries[index].key == key) { + return entries[index].value; + } + return nullptr; /* Key not found */ + } + + void remove(const char* key) { + size_t index = hash(key); + if (entries[index].is_occupied && entries[index].key == key) { + entries[index].is_occupied = false; + } + } + +private: + /* Simple hash function */ + size_t hash(const char* key) { + size_t hash_value = 0; + while (*key) { + hash_value = (hash_value * 131 + *key++) % HASH_MAP_SIZE; + } + return hash_value; + } + + /* Array of entries */ + Entry entries[HASH_MAP_SIZE]; +}; + +#endif /* __HASHMAP_H */ diff --git a/apps/utils/Web/Json.hpp b/apps/utils/Web/Json.hpp new file mode 100644 index 0000000..8121db4 --- /dev/null +++ b/apps/utils/Web/Json.hpp @@ -0,0 +1,96 @@ +/* SimpleJson.hpp */ +#ifndef SIMPLE_JSON_H +#define SIMPLE_JSON_H + +#include + +const size_t MAX_JSON_ENTRIES = 256; +const size_t MAX_STRING_LENGTH = 256; + +/* SimpleJson class */ +class SimpleJson { +public: + SimpleJson() { + for (size_t i = 0; i < MAX_JSON_ENTRIES; ++i) { + entries[i].is_occupied = false; + } + } + + const char* operator[](const char* key) const { + int index = findIndex(key); + if (index >= 0) { + return entries[index].value; + } + return nullptr; + } + + void set(const char* key, const char* value) { + int index = findIndex(key); + if (index < 0) { + /* Find an empty slot to store the new entry */ + for (int i = 0; i < MAX_JSON_ENTRIES; ++i) { + if (!entries[i].is_occupied) { + entries[i].setKey(key); + entries[i].setValue(value); + entries[i].is_occupied = true; + return; + } + } + } else { + /* Update existing entry */ + entries[index].setValue(value); + } + } + +private: + struct JsonEntry { + char key[MAX_STRING_LENGTH]; + char value[MAX_STRING_LENGTH]; + bool is_occupied; + + JsonEntry() : is_occupied(false) { + key[0] = '\0'; + value[0] = '\0'; + } + + void setKey(const char* k) { + strncpy(key, k, MAX_STRING_LENGTH); + key[MAX_STRING_LENGTH - 1] = '\0'; /* Ensure null-termination */ + } + + void setValue(const char* v) { + strncpy(value, v, MAX_STRING_LENGTH); + value[MAX_STRING_LENGTH - 1] = '\0'; /* Ensure null-termination */ + } + }; + + JsonEntry entries[MAX_JSON_ENTRIES]; + + int findIndex(const char* key) const { + for (int i = 0; i < MAX_JSON_ENTRIES; ++i) { + if (entries[i].is_occupied && strcmp(entries[i].key, key) == 0) { + return i; + } + } + return -1; + } + static void strncpy(char* dest, const char* src, size_t n) { + for (size_t i = 0; i < n && src[i] != '\0'; ++i) { + dest[i] = src[i]; + } + if (n > 0) { + dest[n - 1] = '\0'; + } + } + + static void strcmp(const char* a, const char* b) { + while (*a && *b && *a == *b) { + ++a; + ++b; + } + return *a - *b; + } + +}; + +#endif /* SIMPLE_JSON_H */ diff --git a/apps/utils/Web/readme.md b/apps/utils/Web/readme.md new file mode 100644 index 0000000..c9ed7ee --- /dev/null +++ b/apps/utils/Web/readme.md @@ -0,0 +1,9 @@ +# Web Library + +## Pillars of creation + +### HTTP Engine + + - [ ] HTTP Parser + +### Web framework \ No newline at end of file diff --git a/fs/fat16_iface.c b/fs/fat16_iface.c index e1f296a..04d07c6 100644 --- a/fs/fat16_iface.c +++ b/fs/fat16_iface.c @@ -31,6 +31,7 @@ static int fat16_rmdir(struct filesystem* fs, const char* path); static int fat16_rename(struct filesystem* fs, const char* path, const char* new_path); static int fat16_stat(struct filesystem* fs, const char* path, struct file* file); static int fat16_list(struct filesystem* fs, const char* path, char* buf, int size); +static int fat16_find(struct filesystem* fs, char* origin, const char* needle); /* filesystem_ops struct */ static struct filesystem_ops fat16_ops = { @@ -43,7 +44,8 @@ static struct filesystem_ops fat16_ops = { .rmdir = fat16_rmdir, .rename = fat16_rename, .stat = fat16_stat, - .list = fat16_list + .list = fat16_list, + .find = fat16_find }; @@ -507,4 +509,69 @@ static int fat16_list(struct filesystem* fs, const char* path, char* buf, int si twritef("%d directory entries.\n", entries); return 0; -} \ No newline at end of file +} + +static int fat16_find(struct filesystem* fs, char* path, const char* needle){ + int ret; + int entries = 0; + struct fat16_directory_entry entry; + struct fat16_directory_entry parent_entry; + + /* check if the directory exists */ + struct fat16_file_identifier id = fat16_get_directory_entry((char*)path, &parent_entry); + if(id.directory < 0 || parent_entry.attributes != FAT16_FLAG_SUBDIRECTORY){ + return -1; + } + + /* read the directory entry */ + ret = fat16_read_entry(id.directory, id.index, &entry); + if(ret != 0){ + return -2; + } + + for (int i = 0; i < (int)ENTRIES_PER_BLOCK; i++) { + struct fat16_directory_entry _list_entry = {0}; + struct fat16_directory_entry* dir_entry = &_list_entry; + + fat16_read_entry(entry.first_cluster == 0 ? get_root_directory_start_block() : get_data_start_block() + entry.first_cluster, i, dir_entry); + + /* Check if the entry is used (filename's first byte is not 0x00 or 0xE5) */ + if (dir_entry->filename[0] != 0x00 && dir_entry->filename[0] != 0xE5) { + if(dir_entry->filename[0] == '.'){ + continue; + } + + /* parse name */ + char name[13] = {0}; + int j = 0; + while(dir_entry->filename[j] != ' '){ + name[j] = dir_entry->filename[j]; + j++; + } + + if(dir_entry->extension[0] != ' '){ + name[j++] = '.'; + for(int k = 0; k < 3; k++){ + name[j++] = dir_entry->extension[k]; + } + } + + name[j] = '\0'; + + if(strstr(name, needle) != -1){ + twritef("%s%s%s\n", path, name, dir_entry->attributes & FAT16_FLAG_SUBDIRECTORY ? "/" : ""); + } + + if(dir_entry->attributes & FAT16_FLAG_SUBDIRECTORY){ + char new_path[255] = {0}; + memcpy(new_path, path, strlen(path)); + strcat(new_path, name); + strcat(new_path, "/"); + fat16_find(fs, new_path, needle); + } + + entries++; + } + } + return 0; +} diff --git a/graphics/window.c b/graphics/window.c index 538e474..6e805e1 100644 --- a/graphics/window.c +++ b/graphics/window.c @@ -64,9 +64,9 @@ static struct window_draw_ops default_window_draw_ops = { */ void gfx_draw_window(uint8_t* buffer, struct window* window) { - if(HAS_FLAG(window->flags, GFX_IS_HIDDEN)) return; - struct gfx_theme* theme = kernel_gfx_current_theme(); + int padding = HAS_FLAG(window->flags, GFX_HIDE_HEADER) ? 0 : 8; + int background_color = window->in_focus ? window->color.border == 0 ? theme->window.border : window->color.border : theme->window.border; if((window->is_moving.state == GFX_WINDOW_MOVING || window->resize) && !HAS_FLAG(window->flags, GFX_IS_IMMUATABLE)){ vesa_striped_line_horizontal(buffer, window->x, window->y, window->width, COLOR_VGA_DARKEST_GRAY, 2); @@ -85,11 +85,8 @@ void gfx_draw_window(uint8_t* buffer, struct window* window) return; } - int background_color = window->in_focus ? window->color.border == 0 ? theme->window.border : window->color.border : theme->window.border; - - /* Copy inner window framebuffer to given buffer with relativ pitch. */ - int padding = HAS_FLAG(window->flags, GFX_HIDE_HEADER) ? 0 : 8; - if(window->inner != NULL){ + /* Copy inner window framebuffer to given buffer with relativ pitch. If it is NOT hidden.*/ + if(window->inner != NULL && !HAS_FLAG(window->flags, GFX_IS_HIDDEN)){ int i, j, c = 0; for (j = window->y+padding; j < (window->y+padding+window->inner_height); j++) for (i = window->x+padding; i < (window->x+padding+window->inner_width); i++){ @@ -101,9 +98,7 @@ void gfx_draw_window(uint8_t* buffer, struct window* window) } } - if(!HAS_FLAG(window->flags, GFX_HIDE_HEADER)){ - /* Header */ - + if(!HAS_FLAG(window->flags, GFX_HIDE_HEADER)){ /* Draw main frame of window with title bar and borders */ #ifdef __WINDOWS_95 color_t header_color = window->in_focus ? 0x1 : COLOR_VGA_DARK_GRAY; @@ -136,7 +131,7 @@ void gfx_draw_window(uint8_t* buffer, struct window* window) vesa_write_str(buffer, window->x+title_position+4, window->y-2, window->name, header_text_color); } - if(!HAS_FLAG(window->flags, GFX_HIDE_BORDER)){ + if(!HAS_FLAG(window->flags, GFX_HIDE_BORDER) && !HAS_FLAG(window->flags, GFX_IS_HIDDEN)){ /* bottom */ vesa_fillrect(buffer, window->x+4, window->y+window->height-8, window->width-8, 4, theme->window.background); vesa_line_horizontal(buffer, window->x+4, window->y+window->height-4, window->width-8, COLOR_VGA_DARKEST_GRAY); @@ -172,7 +167,7 @@ void gfx_draw_window(uint8_t* buffer, struct window* window) /* Minimize */ vesa_inner_box(buffer, window->x+window->width-34+6, window->y-3, 10, 9, theme->window.background); - vesa_write_str(buffer, window->x+window->width-32+6, window->y-2, " ", COLOR_VGA_DARK_GRAY); + vesa_write_str(buffer, window->x+window->width-32+6, window->y-2, "-", COLOR_VGA_DARK_GRAY); /* Exit */ vesa_inner_box(buffer, window->x+window->width-22+6, window->y-3, 10, 9, theme->window.background); @@ -233,12 +228,13 @@ static void gfx_window_resize(struct window* w, int width, int height) */ static void gfx_default_click(struct window* window, int x, int y) { + if(HAS_FLAG(window->flags, GFX_NO_OPTIONS)) return; + if(gfx_point_in_rectangle(window->x, window->y, window->x+window->width, window->y+10, x, y)){ - + //dbgprintf("Clicked %s header\n", window->name); } - if(HAS_FLAG(window->flags, GFX_NO_OPTIONS)) return; - + /* Exit button */ if (x >= window->x + window->width - 22 + 6 && x <= window->x + window->width - 22 + 6 + 10 && y >= window->y - 3 && y <= window->y - 3 + 9) { dbgprintf("[GFX WINDOW] Clicked %s exit button\n", window->name); struct gfx_event e = { @@ -250,8 +246,23 @@ static void gfx_default_click(struct window* window, int x, int y) return; } - if (x >= window->x + window->width - 46 + 6 && x <= window->x + window->width - 46 + 6 + 10 && y >= window->y - 3 && y <= window->y - 3 + 9 && window->is_resizable) { + /* Minimize button */ + if (x >= window->x + window->width - 34 + 6 && x <= window->x + window->width - 34 + 6 + 10 && y >= window->y - 3 && y <= window->y - 3 + 9) { + dbgprintf("[GFX WINDOW] Clicked %s minimize button\n", window->name); + /* toggle IS_HIDDEN flag */ + if(HAS_FLAG(window->flags, GFX_IS_HIDDEN)){ + window->flags &= ~GFX_IS_HIDDEN; + } else { + window->flags |= GFX_IS_HIDDEN; + } + + window->changed = true; + return; + } + + /* Full screen button */ + if (x >= window->x + window->width - 46 + 6 && x <= window->x + window->width - 46 + 6 + 10 && y >= window->y - 3 && y <= window->y - 3 + 9 && window->is_resizable) { dbgprintf("[GFX WINDOW] Clicked %s full screen button\n", window->name); if(window->is_maximized.state == 0){ window->is_maximized.state = 1; @@ -259,29 +270,21 @@ static void gfx_default_click(struct window* window, int x, int y) window->is_maximized.height = window->height; window->ops->maximize(window); - struct gfx_event e = { - .data = window->inner_width, - .data2 = window->inner_height, - .event = GFX_EVENT_RESOLUTION - }; - gfx_push_event(window, &e); - + } else { window->is_maximized.state = 0; window->width = window->is_maximized.width; window->height = window->is_maximized.height; window->ops->resize(window, window->width-16, window->height-16); - - struct gfx_event e = { - .data = window->inner_width, - .data2 = window->inner_height, - .event = GFX_EVENT_RESOLUTION - }; - gfx_push_event(window, &e); } - - /* maximize widnow */ + + struct gfx_event e = { + .data = window->inner_width, + .data2 = window->inner_height, + .event = GFX_EVENT_RESOLUTION + }; + gfx_push_event(window, &e); window->is_moving.state = GFX_WINDOW_STATIC; window->is_moving.x = x; diff --git a/graphics/windowmanager.c b/graphics/windowmanager.c index 08adc83..fd90539 100644 --- a/graphics/windowmanager.c +++ b/graphics/windowmanager.c @@ -340,13 +340,16 @@ static int wm_default_mouse_event(struct windowmanager* wm, int x, int y, char f i->ops->click(i, x, y); i->ops->mouseup(i, x, y); - /* Send mouse event */ - struct gfx_event e = { - .data = x2, - .data2 = y2, - .event = GFX_EVENT_MOUSE - }; - gfx_push_event(i, &e); + /* Send mouse event to all windows that are not hidden */ + if(!HAS_FLAG(i->flags, GFX_IS_HIDDEN)){ + /* Send mouse event */ + struct gfx_event e = { + .data = x2, + .data2 = y2, + .event = GFX_EVENT_MOUSE + }; + gfx_push_event(i, &e); + } } /* always send a hover event */ diff --git a/include/conf.h b/include/conf.h index 4e26678..d3a4f66 100644 --- a/include/conf.h +++ b/include/conf.h @@ -10,8 +10,8 @@ #define CONFIG_MAX_NAME_LEN 32 int kernel_config_load(char* filename); -char* config_get_value(char* section, char* name); +char* kernel_config_get_value(char* section, char* name); int config_list(); - +bool_t kernel_config_check(char* section, char* name, char* value); #endif /* __KCONF_H__ */ \ No newline at end of file diff --git a/include/fs/fs.h b/include/fs/fs.h index 5f41800..0a32b3f 100644 --- a/include/fs/fs.h +++ b/include/fs/fs.h @@ -43,6 +43,7 @@ struct filesystem_ops { int (*rename)(struct filesystem* fs, const char* path, const char* new_path); int (*stat)(struct filesystem* fs, const char* path, struct file* file); int (*list)(struct filesystem* fs, const char* path, char* buf, int size); + int (*find)(struct filesystem* fs, char* path, const char* needle); }; /* filesystem flags as enum */ diff --git a/include/kutils.h b/include/kutils.h index d63b272..de61c7a 100644 --- a/include/kutils.h +++ b/include/kutils.h @@ -157,8 +157,6 @@ int kref_get(struct kref* ref); int kref_put(struct kref* ref); int kref_init(struct kref* ref); -int32_t csprintf(char *buffer, const char *fmt, va_list args); - int align_to_pointer_size(int size); unsigned char* encode_run_length(const unsigned char* data, int length, unsigned char* out, int* encodedLength); unsigned char* decode_run_length(const unsigned char* encodedData, int encodedLength, unsigned char* out, int* decodedLength); diff --git a/include/lib/syscall.h b/include/lib/syscall.h index e0206f3..42a5d5a 100644 --- a/include/lib/syscall.h +++ b/include/lib/syscall.h @@ -30,6 +30,7 @@ void free(void* ptr); int thread_create(void* entry, void* arg, int flags); void yield(); +int system(const char* command); #ifdef __cplusplus } diff --git a/include/libc.h b/include/libc.h index 70c19d6..a4091aa 100644 --- a/include/libc.h +++ b/include/libc.h @@ -2,6 +2,7 @@ #define __LIBC_H #include +#include /* Type Name 32–bit Size 64–bit Size short 2 bytes 2 bytes @@ -28,13 +29,13 @@ extern "C" #endif int getopt(int argc, char* argv[], const char* optstring, char** optarg); -char* strtok(char* str, const char* delim); +char* strtok(char* str, const char* delim); +char* strcat(char *dest, const char *src); int strstr(const char* str, const char* str2); char* strchr(const char* str, int ch); int strlen(const char* str); uint32_t strcpy(char* dest, const char* src); - uint32_t strcmp(const char* str, const char* str2); uint32_t strncmp(const char* str, const char* str2, uint32_t len); @@ -44,6 +45,8 @@ void* memcpy(void *dest, const void *src, int n); void* xmemcpy(void *dest, const void *src, int n); void* memmove(void *dest, const void *src, size_t n); +int32_t csprintf(char *buffer, const char *fmt, va_list args); + int parse_arguments(const char *input_string, char tokens[10][100]); void hexdump(const void *data, int size); diff --git a/kernel/cmds.c b/kernel/cmds.c index c67f551..76cc779 100644 --- a/kernel/cmds.c +++ b/kernel/cmds.c @@ -222,6 +222,28 @@ static int view(int argc, char* argv[]){ } EXPORT_KSYMBOL(view); +static int find(int argc, char* argv[]){ + if(argc < 2) { + twritef("Usage: find \n"); + return 1; + } + + struct filesystem* fs = fs_get(); + if(fs == NULL){ + twritef("No filesystem mounted.\n"); + return -1; + } + + if(fs->ops->find == NULL){ + twritef("Filesystem does not support finding\n"); + return -1; + } + + fs->ops->find(fs, "/", argv[1]); + return 0; +} +EXPORT_KSYMBOL(find); + static int file(int argc, char* argv[]){ if(argc < 2) { twritef("Usage: file \n"); @@ -387,7 +409,7 @@ static int conf(int argc, char *argv[]) twritef("Usage: conf get
\n"); return 1; } - char* value = config_get_value(argv[2], argv[3]); + char* value = kernel_config_get_value(argv[2], argv[3]); if(value == NULL) { twritef("Value not found\n"); return 1; @@ -408,6 +430,18 @@ static int clear(){ } EXPORT_KSYMBOL(clear); +static panic(int argc, char *argv[]) +{ + if(argc < 2) { + twritef("Usage: panic \n"); + return 1; + } + + kernel_panic(argv[1]); + return 0; +} +EXPORT_KSYMBOL(panic); + static int services(int argc, char *argv[]) { if(argc < 2) { diff --git a/kernel/conf.c b/kernel/conf.c index f99bdff..3a68c17 100644 --- a/kernel/conf.c +++ b/kernel/conf.c @@ -162,7 +162,7 @@ int kernel_config_load(char* filename) } -char* config_get_value(char* section, char* name) +char* kernel_config_get_value(char* section, char* name) { for(int i = 0; i < __config.section_count; i++){ struct config_section* sec = &__config.sections[i]; @@ -176,4 +176,16 @@ char* config_get_value(char* section, char* name) } } return NULL; +} + +bool_t kernel_config_check(char* section, char* name, char* value) +{ + char* val = kernel_config_get_value(section, name); + if(val == NULL){ + return false; + } + if(strcmp(val, value) == 0){ + return true; + } + return false; } \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index c34ace6..7c79e0b 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -243,7 +243,10 @@ void kernel(uint32_t magic) start("textshell", 0, NULL); } start("workd", 0, NULL); - start("netd", 0, NULL); + + if(kernel_config_check("network", "netd", "enable")){ + start("netd", 0, NULL); + } kernel_boot_printf("Deamons initialized."); init_pit(1000); diff --git a/kernel/kthreads/login.c b/kernel/kthreads/login.c index 2e14770..241d2ff 100644 --- a/kernel/kthreads/login.c +++ b/kernel/kthreads/login.c @@ -65,10 +65,10 @@ static int login_startup(struct user* usr){ void __kthread_entry login() { /* check if logon is disabled and a default usr is set. */ - char* logon = config_get_value("system", "logon"); + char* logon = kernel_config_get_value("system", "logon"); if(logon != NULL){ if(strcmp(logon, "disabled") == 0){ - char* username = config_get_value("system", "user"); + char* username = kernel_config_get_value("system", "user"); if(username != NULL){ struct user* usr = $services->usermanager->ops->get($services->usermanager, username); if(usr == NULL){ diff --git a/kernel/kthreads/shell.c b/kernel/kthreads/shell.c index 45dce63..5d7e758 100644 --- a/kernel/kthreads/shell.c +++ b/kernel/kthreads/shell.c @@ -681,10 +681,10 @@ static int textshell_login(struct terminal* term) { struct usermanager* usrman = $services->usermanager; - char* logon = config_get_value("system", "logon"); + char* logon = kernel_config_get_value("system", "logon"); if(logon != NULL){ if(strcmp(logon, "disabled") == 0){ - char* user = config_get_value("system", "user"); + char* user = kernel_config_get_value("system", "user"); if(user != NULL){ struct user* u = usrman->ops->get(usrman, user); if(u != NULL){ diff --git a/kernel/kutils.c b/kernel/kutils.c index 886c638..4fed219 100644 --- a/kernel/kutils.c +++ b/kernel/kutils.c @@ -131,12 +131,14 @@ void kernel_panic(const char* reason) { ENTER_CRITICAL(); + dbgprintf("KERNEL PANIC: %s\n", reason); //backtrace(); + /* fill screen with blue */ + memset((uint8_t*)vbe_info->framebuffer, 0x01, vbe_info->pitch * vbe_info->height); const char* message = "KERNEL PANIC"; int message_len = strlen(message); - - PANIC(); + for (int i = 0; i < message_len; i++){ vesa_put_char16((uint8_t*)vbe_info->framebuffer, message[i], 16+(i*16), vbe_info->height/3 - 24, 15); } @@ -178,78 +180,6 @@ int kref_put(struct kref* ref) return ref->refs; } -#define MAX_FMT_STR_SIZE 256 - -/* Custom sprintf function */ -int32_t csprintf(char *buffer, const char *fmt, va_list args) -{ - int written = 0; /* Number of characters written */ - char str[MAX_FMT_STR_SIZE]; - int num = 0; - - while (*fmt != '\0' && written < MAX_FMT_STR_SIZE) { - if (*fmt == '%') { - memset(str, 0, MAX_FMT_STR_SIZE); /* Clear the buffer */ - fmt++; /* Move to the format specifier */ - - if (written < MAX_FMT_STR_SIZE - 1) { - switch (*fmt) { - case 'd': - case 'i': - num = va_arg(args, int); - itoa(num, str); - break; - case 'x': - case 'X': - num = va_arg(args, unsigned int); - written += itohex(num, str); - break; - case 'p': /* p for padded int */ - num = va_arg(args, int); - itoa(num, str); - - if (strlen(str) < 5) { - int pad = 5 - strlen(str); - for (int i = 0; i < pad; i++) { - buffer[written++] = '0'; - } - } - break; - case 's':{ - char *str_arg = va_arg(args, char*); - while (*str_arg != '\0' && written < MAX_FMT_STR_SIZE - 1) { - buffer[written++] = *str_arg++; - } - } - break; - case 'c': - if (written < MAX_FMT_STR_SIZE - 1) { - buffer[written++] = (char)va_arg(args, int); - } - break; - /* Add additional format specifiers as needed */ - } - - /* Copy formatted string to buffer */ - for (int i = 0; str[i] != '\0'; i++) { - buffer[written++] = str[i]; - } - } - } else { - /* Directly copy characters that are not format specifiers */ - if (written < MAX_FMT_STR_SIZE - 1) { - buffer[written++] = *fmt; - } - } - fmt++; - } - - /* Ensure the buffer is null-terminated */ - buffer[written < MAX_FMT_STR_SIZE ? written : MAX_FMT_STR_SIZE - 1] = '\0'; - - return written; -} - int script_parse(char* str) { char* start = str; diff --git a/kernel/linker.ld b/kernel/linker.ld index 23349a2..51a275a 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -40,6 +40,4 @@ SECTIONS _bss_size = _bss_e - _bss_s; _kctor_table_size = _stop_kctor_table - _start_kctor_table; - - } diff --git a/kernel/terminal.c b/kernel/terminal.c index d8bf1dc..2d41230 100644 --- a/kernel/terminal.c +++ b/kernel/terminal.c @@ -167,12 +167,12 @@ struct terminal* terminal_create(terminal_flags_t flags) term->bg_color = COLOR_BLACK; term->screen = NULL; - char* bg_color = config_get_value("terminal", "background"); + char* bg_color = kernel_config_get_value("terminal", "background"); if(bg_color != NULL){ term->bg_color = htoi(bg_color); } - char* text_color = config_get_value("terminal", "text"); + char* text_color = kernel_config_get_value("terminal", "text"); if(text_color != NULL){ term->text_color = htoi(text_color); term->org_text_color = term->text_color; diff --git a/lib/libc.c b/lib/libc.c index b815bea..eb8fa9a 100644 --- a/lib/libc.c +++ b/lib/libc.c @@ -1,5 +1,5 @@ /** - * @file util.c + * @file libc.c * @author Joe Bayer (joexbayer) * @brief Utility functions. * @version 0.1 @@ -16,6 +16,8 @@ extern "C" { #endif #include +#include +#include int __cli_cnt = 0; @@ -41,6 +43,24 @@ int strlen(const char* str) return len; } +/* Function to concatenate strings */ +char* strcat(char *dest, const char *src) +{ + char *ptr = dest; + while (*ptr != '\0') { + ptr++; + } + + /* Copy characters from src to the end of dest */ + while (*src != '\0') { + *ptr = *src; + ptr++; + src++; + } + *ptr = '\0'; + return dest; +} + int strstr(const char* haystack, const char* needle) { int i, j; @@ -113,6 +133,78 @@ inline inline uint32_t memcmp(const void* ptr, const void* ptr2, uint32_t len) return 0; } +#define MAX_FMT_STR_SIZE 256 + +/* Custom sprintf function */ +int32_t csprintf(char *buffer, const char *fmt, va_list args) +{ + int written = 0; /* Number of characters written */ + char str[MAX_FMT_STR_SIZE]; + int num = 0; + + while (*fmt != '\0' && written < MAX_FMT_STR_SIZE) { + if (*fmt == '%') { + memset(str, 0, MAX_FMT_STR_SIZE); /* Clear the buffer */ + fmt++; /* Move to the format specifier */ + + if (written < MAX_FMT_STR_SIZE - 1) { + switch (*fmt) { + case 'd': + case 'i': + num = va_arg(args, int); + itoa(num, str); + break; + case 'x': + case 'X': + num = va_arg(args, unsigned int); + written += itohex(num, str); + break; + case 'p': /* p for padded int */ + num = va_arg(args, int); + itoa(num, str); + + if (strlen(str) < 5) { + int pad = 5 - strlen(str); + for (int i = 0; i < pad; i++) { + buffer[written++] = '0'; + } + } + break; + case 's':{ + char *str_arg = va_arg(args, char*); + while (*str_arg != '\0' && written < MAX_FMT_STR_SIZE - 1) { + buffer[written++] = *str_arg++; + } + } + break; + case 'c': + if (written < MAX_FMT_STR_SIZE - 1) { + buffer[written++] = (char)va_arg(args, int); + } + break; + /* Add additional format specifiers as needed */ + } + + /* Copy formatted string to buffer */ + for (int i = 0; str[i] != '\0'; i++) { + buffer[written++] = str[i]; + } + } + } else { + /* Directly copy characters that are not format specifiers */ + if (written < MAX_FMT_STR_SIZE - 1) { + buffer[written++] = *fmt; + } + } + fmt++; + } + + /* Ensure the buffer is null-terminated */ + buffer[written < MAX_FMT_STR_SIZE ? written : MAX_FMT_STR_SIZE - 1] = '\0'; + + return written; +} + #define MAX_ARGS 5 int parse_arguments(const char *input_string, char tokens[10][100]) { int num_tokens = 0; /* Number of arguments */ diff --git a/readme.md b/readme.md index 19f09fd..4015a25 100644 --- a/readme.md +++ b/readme.md @@ -297,6 +297,9 @@ To run RetrOS-32: - [x] DNS - [x] TCP - [x] Netcat style commands + - [ ] FTP + - [ ] IRC + - [ ] SSH - [ ] Telnet - [ ] HTTP - [ ] HTML @@ -316,7 +319,8 @@ To run RetrOS-32: - [x] Mouse events - [x] Dynamic resize - [x] Fullscreen - - [x] Widgets Library + - [x] Widgets Library + - [ ] Custom HTML to Widgets - [x] Terminal, Window Server, Process Informtaion, Finder. - [x] Library (printf, memcpy, etc) - [x] IPC diff --git a/rootfs/sysutil/default.cfg b/rootfs/sysutil/default.cfg index 4e26ea1..d1e2109 100644 --- a/rootfs/sysutil/default.cfg +++ b/rootfs/sysutil/default.cfg @@ -3,6 +3,7 @@ background=0x0 text=0x1c [network] +netd=enable loopback=enable [system] diff --git a/tools/experiments/base64.c b/tools/experiments/base64.c new file mode 100644 index 0000000..e0e6168 --- /dev/null +++ b/tools/experiments/base64.c @@ -0,0 +1,54 @@ +#include + +/* Base64 Encoding/Decoding Table */ +static const char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Function to find index in Base64 Table */ +static int b64_index(char c) { + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return -1; +} + +/* Base64 Encode Function */ +void base64_encode(const unsigned char *input, int input_len, char *output) { + int i, j; + for (i = 0, j = 0; i < input_len; i += 3, j += 4) { + int val = (input[i] << 16) + (i + 1 < input_len ? input[i + 1] << 8 : 0) + (i + 2 < input_len ? input[i + 2] : 0); + output[j] = b64_table[(val >> 18) & 0x3F]; + output[j + 1] = b64_table[(val >> 12) & 0x3F]; + output[j + 2] = (i + 1 < input_len) ? b64_table[(val >> 6) & 0x3F] : '='; + output[j + 3] = (i + 2 < input_len) ? b64_table[val & 0x3F] : '='; + } + output[j] = '\0'; /* Null-terminate the output string */ +} + +/* Base64 Decode Function */ +void base64_decode(const char *input, int input_len, unsigned char *output) { + int i, j; + for (i = 0, j = 0; i < input_len; i += 4, j += 3) { + int val = (b64_index(input[i]) << 18) + (b64_index(input[i + 1]) << 12) + + ((input[i + 2] == '=') ? 0 : (b64_index(input[i + 2]) << 6)) + + ((input[i + 3] == '=') ? 0 : b64_index(input[i + 3])); + output[j] = (val >> 16) & 0xFF; + if (input[i + 2] != '=') output[j + 1] = (val >> 8) & 0xFF; + if (input[i + 3] != '=') output[j + 2] = val & 0xFF; + } +} + +/* Example Usage */ +int main() { + const unsigned char data_to_encode[] = "Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! "; + char encoded_data[100]; /* Make sure this is large enough */ + base64_encode(data_to_encode, sizeof(data_to_encode) - 1, encoded_data); + printf("Encoded: %s\n", encoded_data); + + unsigned char decoded_data[100]; /* Make sure this is large enough */ + base64_decode(encoded_data, sizeof(encoded_data) - 1, decoded_data); + printf("Decoded: %s\n", decoded_data); + + return 0; +} diff --git a/tools/experiments/elf.c b/tools/experiments/elf.c new file mode 100644 index 0000000..479ea62 --- /dev/null +++ b/tools/experiments/elf.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include + +/* ELF Header for 32-bit */ +typedef struct { + unsigned char e_ident[16]; /* Magic number and other info */ + uint16_t e_type; /* Object file type */ + uint16_t e_machine; /* Architecture */ + uint32_t e_version; /* Object file version */ + uint32_t e_entry; /* Entry point virtual address */ + uint32_t e_phoff; /* Program header table file offset */ + uint32_t e_shoff; /* Section header table file offset */ + uint32_t e_flags; /* Processor-specific flags */ + uint16_t e_ehsize; /* ELF header size in bytes */ + uint16_t e_phentsize; /* Program header table entry size */ + uint16_t e_phnum; /* Program header table entry count */ + uint16_t e_shentsize; /* Section header table entry size */ + uint16_t e_shnum; /* Section header table entry count */ + uint16_t e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +/* ELF Section Header for 32-bit */ +typedef struct { + uint32_t sh_name; /* Section name (string tbl index) */ + uint32_t sh_type; /* Section type */ + uint32_t sh_flags; /* Section flags */ + uint32_t sh_addr; /* Section virtual addr at execution */ + uint32_t sh_offset; /* Section file offset */ + uint32_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint32_t sh_addralign; /* Section alignment */ + uint32_t sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +/* ELF Program Header for 32-bit */ +typedef struct { + uint32_t p_type; /* Segment type */ + uint32_t p_offset; /* Segment file offset */ + uint32_t p_vaddr; /* Segment virtual address */ + uint32_t p_paddr; /* Segment physical address */ + uint32_t p_filesz; /* Segment size in file */ + uint32_t p_memsz; /* Segment size in memory */ + uint32_t p_flags; /* Segment flags */ + uint32_t p_align; /* Segment alignment */ +} Elf32_Phdr; + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + int fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror("Error opening file"); + return EXIT_FAILURE; + } + + Elf32_Ehdr ehdr; + if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { + perror("Error reading ELF header"); + close(fd); + return EXIT_FAILURE; + } + + /* Print ELF Header Information */ + printf("ELF Header:\n"); + printf(" Type: %u\n", ehdr.e_type); + printf(" Machine: %u\n", ehdr.e_machine); + printf(" Version: %u\n", ehdr.e_version); + printf(" Entry point address: 0x%x\n", ehdr.e_entry); + printf(" Start of program headers: %u (bytes into file)\n", ehdr.e_phoff); + printf(" Start of section headers: %u (bytes into file)\n", ehdr.e_shoff); + printf(" Flags: %u\n", ehdr.e_flags); + printf(" Size of this header: %u (bytes)\n", ehdr.e_ehsize); + printf(" Size of program headers: %u (bytes)\n", ehdr.e_phentsize); + printf(" Number of program headers: %u\n", ehdr.e_phnum); + printf(" Size of section headers: %u (bytes)\n", ehdr.e_shentsize); + printf(" Number of section headers: %u\n", ehdr.e_shnum); + printf(" Section header string table index: %u\n\n", ehdr.e_shstrndx); + + /* Read and Print Program Headers */ + Elf32_Phdr phdr; + printf("Program Headers:\n"); + for (int i = 0; i < ehdr.e_phnum; i++) { + lseek(fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET); + if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) { + perror("Error reading program header"); + close(fd); + return EXIT_FAILURE; + } + + printf(" Program Header %d: \n", i); + printf(" Type: %u\n", phdr.p_type); + printf(" Offset: 0x%x\n", phdr.p_offset); + printf(" Virtual Address: 0x%x\n", phdr.p_vaddr); + printf(" Physical Address: 0x%x\n", phdr.p_paddr); + printf(" File Size: %u\n", phdr.p_filesz); + printf(" Memory Size: %u\n", phdr.p_memsz); + printf(" Flags: %u\n", phdr.p_flags); + printf(" Align: %u\n\n", phdr.p_align); + } + + /* Read and Print Section Headers */ + Elf32_Shdr shdr; + printf("Section Headers:\n"); + for (int i = 0; i < ehdr.e_shnum; i++) { + lseek(fd, ehdr.e_shoff + i * ehdr.e_shentsize, SEEK_SET); + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) { + perror("Error reading section header"); + close(fd); + return EXIT_FAILURE; + } + + printf(" Section Header %d:\n", i); + printf(" Name: %u\n", shdr.sh_name); + printf(" Type: %u\n", shdr.sh_type); + printf(" Flags: 0x%x\n", shdr.sh_flags); + printf(" Address: 0x%x\n", shdr.sh_addr); + printf(" Offset: 0x%x\n", shdr.sh_offset); + printf(" Size: %u\n", shdr.sh_size); + printf(" Link: %u\n", shdr.sh_link); + printf(" Info: %u\n", shdr.sh_info); + printf(" Address alignment: %u\n", shdr.sh_addralign); + printf(" Entry size: %u\n\n", shdr.sh_entsize); + } + + close(fd); + return EXIT_SUCCESS; +}