mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-27 17:42:34 +00:00
fix(vfs): resolve CWD tracking, filename clobbering, touch creation, and nano full-screen editing & saving
This commit is contained in:
1 parent
d680335f05
commit
9f9a19bab0
5 files changed
+289
-130
No files matched your search
@@ -40,7 +40,7 @@
|
||||
// -------------------------------------------------------------
|
||||
|
||||
static int applet_ls(int argc, char** argv) {
|
||||
const char* path = (argc >= 2) ? argv[1] : "/";
|
||||
const char* path = (argc >= 2) ? argv[1] : vfs_getcwd();
|
||||
vfs_node_t* dir = vfs_namei(path);
|
||||
|
||||
if (!dir) {
|
||||
@@ -112,6 +112,8 @@ static int applet_touch(int argc, char** argv) {
|
||||
int fd = vfs_open(argv[i], O_CREAT | O_RDWR);
|
||||
if (fd >= 0) {
|
||||
vfs_close(fd);
|
||||
} else {
|
||||
printk(KERN_ERR "touch: cannot touch '%s': No such file or directory\n", argv[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -141,14 +143,14 @@ static int applet_echo(int argc, char** argv) {
|
||||
|
||||
static int applet_pwd(int argc, char** argv) {
|
||||
(void)argc; (void)argv;
|
||||
printk("/\n");
|
||||
printk("%s\n", vfs_getcwd());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int applet_cd(int argc, char** argv) {
|
||||
const char* target = (argc >= 2) ? argv[1] : "/";
|
||||
vfs_node_t* node = vfs_namei(target);
|
||||
if (!node || !(node->flags & FS_DIRECTORY)) {
|
||||
int res = vfs_chdir(target);
|
||||
if (res != 0) {
|
||||
printk(KERN_ERR "cd: %s: No such file or directory\n", target);
|
||||
return 1;
|
||||
}
|
||||
|
||||
+59
-27
@@ -16,39 +16,46 @@ static int nano_cursor_row = 0;
|
||||
static int nano_cursor_col = 0;
|
||||
static int nano_top_row = 0;
|
||||
static bool nano_modified = false;
|
||||
static char nano_filename[128];
|
||||
static char nano_status[80];
|
||||
static char nano_filename[256];
|
||||
static char nano_status[128];
|
||||
static char nano_cut_buffer[NANO_LINE_LEN];
|
||||
static bool nano_has_cut = false;
|
||||
|
||||
static void nano_render(void) {
|
||||
tty_clear();
|
||||
|
||||
// 1. Title bar (Inverted Color)
|
||||
printk(ANSI_INVERT " GNU nano 2.0.0 File: %-32s %s" ANSI_RESET "\n",
|
||||
nano_filename[0] ? nano_filename : "New Buffer",
|
||||
nano_modified ? "[Modified]" : " ");
|
||||
// 1. Title bar (Row 0)
|
||||
tty_set_cursor(0, 0);
|
||||
char title[128];
|
||||
snprintf(title, sizeof(title), " GNU nano 2.0.0 File: %-32s %s",
|
||||
nano_filename[0] ? nano_filename : "New Buffer",
|
||||
nano_modified ? "[Modified]" : " ");
|
||||
printk(ANSI_INVERT "%-80s" ANSI_RESET, title);
|
||||
|
||||
// 2. Viewport Lines (Rows 1 to 21)
|
||||
for (int r = 0; r < NANO_SCREEN_ROWS; r++) {
|
||||
tty_set_cursor(r + 1, 0);
|
||||
int line_idx = nano_top_row + r;
|
||||
if (line_idx < (int)nano_line_count) {
|
||||
printk("%s\n", nano_lines[line_idx]);
|
||||
printk("\033[K%s", nano_lines[line_idx]);
|
||||
} else {
|
||||
printk("~\n");
|
||||
printk("\033[K" ANSI_BRIGHT_BLACK "~" ANSI_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Status Message Bar
|
||||
printk(ANSI_BRIGHT_CYAN "%-78s" ANSI_RESET "\n", nano_status);
|
||||
// 3. Status Message Bar (Row 22)
|
||||
tty_set_cursor(22, 0);
|
||||
printk(ANSI_BRIGHT_CYAN "\033[K%-78s" ANSI_RESET, nano_status);
|
||||
|
||||
// 4. Shortcut Cheatsheet Footer
|
||||
printk(ANSI_INVERT "^G Get Help ^O WriteOut ^W Where Is ^K Cut Line ^U Paste ^X Exit" ANSI_RESET "\n");
|
||||
// 4. Shortcut Cheatsheet Footer (Row 23)
|
||||
tty_set_cursor(23, 0);
|
||||
printk(ANSI_INVERT "%-80s" ANSI_RESET,
|
||||
"^G Help ^O WriteOut ^W Where Is ^K Cut Line ^U Paste ^X Exit");
|
||||
|
||||
// 5. Position Hardware Cursor
|
||||
int scr_row = (nano_cursor_row - nano_top_row) + 2;
|
||||
int scr_col = nano_cursor_col + 1;
|
||||
tty_set_cursor(scr_row - 1, scr_col - 1);
|
||||
int scr_row = (nano_cursor_row - nano_top_row) + 1;
|
||||
int scr_col = nano_cursor_col;
|
||||
if (scr_row >= 1 && scr_row <= NANO_SCREEN_ROWS) {
|
||||
tty_set_cursor(scr_row, scr_col);
|
||||
}
|
||||
}
|
||||
|
||||
static void nano_save(void) {
|
||||
@@ -59,7 +66,7 @@ static void nano_save(void) {
|
||||
|
||||
int fd = vfs_open(nano_filename, O_CREAT | O_WRONLY | O_TRUNC);
|
||||
if (fd < 0) {
|
||||
strcpy(nano_status, "[ Error opening file for writing ]");
|
||||
strcpy(nano_status, "[ Error: Cannot open file for writing ]");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -78,7 +85,7 @@ static void nano_save(void) {
|
||||
vfs_close(fd);
|
||||
|
||||
nano_modified = false;
|
||||
sprintf(nano_status, "[ Wrote %llu bytes to %s ]", (uint64_t)total_bytes, nano_filename);
|
||||
snprintf(nano_status, sizeof(nano_status), "[ Wrote %llu bytes to %s ]", (uint64_t)total_bytes, nano_filename);
|
||||
}
|
||||
|
||||
static void nano_load(const char* path) {
|
||||
@@ -90,13 +97,21 @@ static void nano_load(const char* path) {
|
||||
nano_modified = false;
|
||||
nano_status[0] = '\0';
|
||||
|
||||
strncpy(nano_filename, path, sizeof(nano_filename) - 1);
|
||||
if (!path || path[0] == '\0') {
|
||||
nano_filename[0] = '\0';
|
||||
nano_line_count = 1;
|
||||
nano_lines[0][0] = '\0';
|
||||
strcpy(nano_status, "[ New Buffer - Use ^O to save ]");
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = vfs_open(path, O_RDONLY);
|
||||
vfs_resolve_path(path, nano_filename, sizeof(nano_filename));
|
||||
|
||||
int fd = vfs_open(nano_filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
nano_line_count = 1;
|
||||
nano_lines[0][0] = '\0';
|
||||
sprintf(nano_status, "[ New File: %s ]", path);
|
||||
snprintf(nano_status, sizeof(nano_status), "[ New File: %s ]", nano_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -129,13 +144,14 @@ static void nano_load(const char* path) {
|
||||
cur_line++;
|
||||
}
|
||||
nano_line_count = cur_line > 0 ? cur_line : 1;
|
||||
sprintf(nano_status, "[ Read %llu line(s) from %s ]", (uint64_t)nano_line_count, path);
|
||||
snprintf(nano_status, sizeof(nano_status), "[ Read %llu line(s) from %s ]", (uint64_t)nano_line_count, nano_filename);
|
||||
}
|
||||
|
||||
int nano_main(int argc, char** argv) {
|
||||
tty_clear();
|
||||
|
||||
if (argc < 2) {
|
||||
nano_load("");
|
||||
strcpy(nano_status, "[ New Buffer - Use ^O to save ]");
|
||||
} else {
|
||||
nano_load(argv[1]);
|
||||
}
|
||||
@@ -162,11 +178,16 @@ int nano_main(int argc, char** argv) {
|
||||
uint16_t key = keyboard_get_key();
|
||||
|
||||
switch (key) {
|
||||
case 0x18: // Ctrl+X -> Exit
|
||||
case 0x18: // Ctrl+X
|
||||
case 0x11: // Ctrl+Q
|
||||
case 27: // ESC
|
||||
case KEY_F10:
|
||||
running = false;
|
||||
break;
|
||||
|
||||
case 0x0F: // Ctrl+O -> Write Out / Save
|
||||
case 0x0F: // Ctrl+O
|
||||
case 0x13: // Ctrl+S
|
||||
case KEY_F2:
|
||||
nano_save();
|
||||
break;
|
||||
|
||||
@@ -200,6 +221,7 @@ int nano_main(int argc, char** argv) {
|
||||
break;
|
||||
|
||||
case 0x07: // Ctrl+G -> Help
|
||||
case KEY_F1:
|
||||
strcpy(nano_status, "[ Help: ^O=Save, ^X=Exit, ^K=Cut, ^U=Paste, Arrows=Move ]");
|
||||
break;
|
||||
|
||||
@@ -250,7 +272,8 @@ int nano_main(int argc, char** argv) {
|
||||
nano_cursor_row + NANO_SCREEN_ROWS : (int)nano_line_count - 1;
|
||||
break;
|
||||
|
||||
case '\n': // Enter -> Split line
|
||||
case '\n':
|
||||
case '\r': // Enter -> Split line
|
||||
if (nano_line_count < NANO_MAX_LINES) {
|
||||
for (int i = (int)nano_line_count; i > nano_cursor_row + 1; i--) {
|
||||
strcpy(nano_lines[i], nano_lines[i - 1]);
|
||||
@@ -286,6 +309,15 @@ int nano_main(int argc, char** argv) {
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_DELETE:
|
||||
if (nano_cursor_col < line_len) {
|
||||
memmove(&nano_lines[nano_cursor_row][nano_cursor_col],
|
||||
&nano_lines[nano_cursor_row][nano_cursor_col + 1],
|
||||
strlen(&nano_lines[nano_cursor_row][nano_cursor_col + 1]) + 1);
|
||||
nano_modified = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (key >= 32 && key <= 126) {
|
||||
char c = (char)key;
|
||||
|
||||
+33
-17
@@ -1,5 +1,6 @@
|
||||
#include <userland/shell.h>
|
||||
#include <userland/lazybox.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <drivers/tty.h>
|
||||
#include <drivers/keyboard.h>
|
||||
#include <drivers/speaker.h>
|
||||
@@ -19,11 +20,14 @@ static int history_count = 0;
|
||||
static int history_head = 0;
|
||||
|
||||
static const char* shell_builtins[] = {
|
||||
"lazybox", "ls", "cat", "touch", "mkdir", "wc", "echo",
|
||||
"md5sum", "sha256sum", "crc32", "ifconfig", "ping", "arp",
|
||||
"hdparm", "uname", "free", "uptime", "dmesg", "sleep", "clear",
|
||||
"help", "neofetch", "calc", "hexdump", "matrix", "history", "tty",
|
||||
"beep", "reboot", "shutdown", NULL
|
||||
"lazybox", "nano", "ls", "cat", "touch", "mkdir", "pwd", "cd", "wc", "echo",
|
||||
"head", "tail", "stat", "cp", "grep", "hexdump", "tts", "alsamixer",
|
||||
"lsmod", "insmod", "rmmod", "md5sum", "sha256sum", "crc32", "rand",
|
||||
"certcheck", "capsh", "ipcs", "ifconfig", "ping", "arp", "dhclient",
|
||||
"nslookup", "hdparm", "lspci", "speaker", "mouse", "virtinfo",
|
||||
"io_uring_test", "uname", "free", "uptime", "dmesg", "ps", "top",
|
||||
"sleep", "reboot", "poweroff", "clear", "help", "neofetch", "calc",
|
||||
"matrix", "history", "tty", "beep", "shutdown", NULL
|
||||
};
|
||||
|
||||
static void history_add(const char* cmd) {
|
||||
@@ -51,26 +55,34 @@ static void redraw_line(const char* prompt, const char* buffer, size_t len, size
|
||||
static void cmd_help(void) {
|
||||
printk(ANSI_BRIGHT_CYAN "================== SUB-OS Production Command Reference ==================\n" ANSI_RESET);
|
||||
printk(ANSI_YELLOW " [File & Storage Tools]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "nano [file]" ANSI_RESET " - Full-screen visual interactive text editor\n");
|
||||
printk(" " ANSI_GREEN "ls [path]" ANSI_RESET " - Directory list with type & inode numbers\n");
|
||||
printk(" " ANSI_GREEN "cat <file>" ANSI_RESET " - Display file contents (supports /proc & /dev)\n");
|
||||
printk(" " ANSI_GREEN "touch / mkdir" ANSI_RESET " - Create files and directories in VFS\n");
|
||||
printk(" " ANSI_GREEN "touch <file>" ANSI_RESET " - Create empty files in VFS\n");
|
||||
printk(" " ANSI_GREEN "mkdir <dir>" ANSI_RESET " - Create directories in VFS\n");
|
||||
printk(" " ANSI_GREEN "cd [dir] / pwd" ANSI_RESET " - Change / Print current working directory\n");
|
||||
printk(" " ANSI_GREEN "hdparm" ANSI_RESET " - Inspect ATA hard disk parameters & sectors\n\n");
|
||||
printk(ANSI_YELLOW " [Sound & Audio]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "tts <text>" ANSI_RESET " - Phonetic formant voice synthesizer\n");
|
||||
printk(" " ANSI_GREEN "alsamixer" ANSI_RESET " - Sound architecture & audio card status\n\n");
|
||||
printk(ANSI_YELLOW " [Kernel & Modules]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "lsmod / insmod / rmmod" ANSI_RESET " - Manage dynamically loadable kernel modules\n\n");
|
||||
printk(ANSI_YELLOW " [Cryptography & Security]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "sha256sum <file>" ANSI_RESET " - FIPS 180-4 SHA-256 secure hash\n");
|
||||
printk(" " ANSI_GREEN "md5sum <file>" ANSI_RESET " - RFC 1321 MD5 message digest\n");
|
||||
printk(" " ANSI_GREEN "crc32 <text>" ANSI_RESET " - IEEE 802.3 32-bit CRC calculation\n\n");
|
||||
printk(" " ANSI_GREEN "crc32 <text>" ANSI_RESET " - IEEE 802.3 32-bit CRC calculation\n");
|
||||
printk(" " ANSI_GREEN "certcheck / capsh" ANSI_RESET " - X.509 keyring & POSIX capabilities\n\n");
|
||||
printk(ANSI_YELLOW " [Networking Suite]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "ifconfig" ANSI_RESET " - Ethernet eth0 configuration & RX/TX metrics\n");
|
||||
printk(" " ANSI_GREEN "ping <ip>" ANSI_RESET " - Send ICMP echo requests with latency ms\n");
|
||||
printk(" " ANSI_GREEN "arp" ANSI_RESET " - Display kernel ARP resolution cache table\n\n");
|
||||
printk(" " ANSI_GREEN "dhclient" ANSI_RESET " - Request IP lease from DHCP server\n");
|
||||
printk(" " ANSI_GREEN "nslookup <host>" ANSI_RESET " - Query DNS domain name server\n\n");
|
||||
printk(ANSI_YELLOW " [System & Diagnostics]\n" ANSI_RESET);
|
||||
printk(" " ANSI_GREEN "neofetch" ANSI_RESET " - System information & OS ASCII badge\n");
|
||||
printk(" " ANSI_GREEN "free / uptime" ANSI_RESET " - Memory metrics and CPU uptime\n");
|
||||
printk(" " ANSI_GREEN "dmesg" ANSI_RESET " - Kernel boot ring buffer log\n");
|
||||
printk(" " ANSI_GREEN "hexdump [addr] [n]" ANSI_RESET " - Memory hex inspector\n");
|
||||
printk(" " ANSI_GREEN "dmesg / ps / top" ANSI_RESET " - Kernel boot log & process manager\n");
|
||||
printk(" " ANSI_GREEN "calc [A] [op] [B]" ANSI_RESET " - Arithmetic calculator (+, -, *, /, %%)\n");
|
||||
printk(" " ANSI_GREEN "matrix" ANSI_RESET " - Digital rain screen animation\n");
|
||||
printk(" " ANSI_GREEN "tty [1-4]" ANSI_RESET " - Switch virtual console (or Alt+F1-F4)\n");
|
||||
printk(" " ANSI_GREEN "reboot / shutdown" ANSI_RESET " - Power management\n");
|
||||
printk(ANSI_BRIGHT_BLACK "Tip: Use TAB for autocomplete, Up/Down for command history.\n" ANSI_RESET);
|
||||
}
|
||||
@@ -240,7 +252,7 @@ static void shell_process(const char* cmd) {
|
||||
}
|
||||
if (argc == 0) return;
|
||||
|
||||
// 1. LazyBox Applets
|
||||
// 1. LazyBox Applets (ls, cat, touch, mkdir, cd, pwd, nano, etc.)
|
||||
if (lazybox_has_applet(argv[0])) {
|
||||
lazybox_run_applet(argv[0], argc, argv);
|
||||
return;
|
||||
@@ -274,8 +286,10 @@ static void shell_process(const char* cmd) {
|
||||
printk(ANSI_YELLOW "Rebooting...\n" ANSI_RESET);
|
||||
pit_sleep(200);
|
||||
outb(0x64, 0xFE);
|
||||
} else if (strcmp(argv[0], "shutdown") == 0) {
|
||||
} else if (strcmp(argv[0], "shutdown") == 0 || strcmp(argv[0], "poweroff") == 0) {
|
||||
printk(ANSI_YELLOW "System halted.\n" ANSI_RESET);
|
||||
outw(0x604, 0x2000);
|
||||
outw(0xB004, 0x2000);
|
||||
while (1) hlt();
|
||||
} else {
|
||||
printk(ANSI_RED "Unknown command: %s. Type 'help' or 'lazybox'.\n" ANSI_RESET, argv[0]);
|
||||
@@ -287,14 +301,16 @@ void shell_run(void) {
|
||||
size_t cmd_len = 0;
|
||||
size_t cursor_pos = 0;
|
||||
int history_idx = -1;
|
||||
|
||||
const char* prompt = ANSI_BRIGHT_GREEN "sub-os> " ANSI_RESET;
|
||||
char prompt[128];
|
||||
|
||||
printk(ANSI_BRIGHT_CYAN "\nWelcome to SUB-OS Modular Monolithic Linux Core!\n" ANSI_RESET);
|
||||
printk("Type '" ANSI_YELLOW "help" ANSI_RESET "', '" ANSI_YELLOW "lazybox" ANSI_RESET "', or '" ANSI_YELLOW "neofetch" ANSI_RESET "' to begin.\n\n");
|
||||
|
||||
while (true) {
|
||||
const char* cwd = vfs_getcwd();
|
||||
snprintf(prompt, sizeof(prompt), ANSI_BRIGHT_GREEN "sub-os:" ANSI_BRIGHT_CYAN "%s" ANSI_BRIGHT_GREEN "> " ANSI_RESET, cwd);
|
||||
printk("%s", prompt);
|
||||
|
||||
cmd_len = 0;
|
||||
cursor_pos = 0;
|
||||
cmd_buffer[0] = '\0';
|
||||
@@ -361,12 +377,12 @@ void shell_run(void) {
|
||||
|
||||
char c = (char)(key & 0xFF);
|
||||
|
||||
if (c == 0x03) {
|
||||
if (c == 0x03) { // Ctrl+C
|
||||
printk("^C\n%s", prompt);
|
||||
cmd_len = 0; cursor_pos = 0; cmd_buffer[0] = '\0';
|
||||
continue;
|
||||
}
|
||||
if (c == 0x0C) {
|
||||
if (c == 0x0C) { // Ctrl+L
|
||||
tty_clear();
|
||||
printk("%s%s", prompt, cmd_buffer);
|
||||
continue;
|
||||
|
||||
Reference in new issue
Block a user