|
|
|
|
@ -1,15 +1,13 @@ |
|
|
|
|
#include "src/kernel/app/terminal.h" |
|
|
|
|
#include "src/kernel/app/cat.h" |
|
|
|
|
#include "src/kernel/app/ls.h" |
|
|
|
|
#include "src/kernel/fs.h" |
|
|
|
|
#include "src/kernel/path.h" |
|
|
|
|
#include "src/kernel/process.h" |
|
|
|
|
#include "src/lib/memory.h" |
|
|
|
|
#include "src/lib/string.h" |
|
|
|
|
#include "src/lib/util.h" |
|
|
|
|
#include "src/user/syscall.h" |
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
static void help(process_t *proc, uint8_t argc, char **argv); |
|
|
|
|
static void cd(process_t *proc, uint8_t argc, char **argv); |
|
|
|
|
static void help(uint8_t argc, char **argv); |
|
|
|
|
static void cd(uint8_t argc, char **argv); |
|
|
|
|
|
|
|
|
|
#define WRITE_S(s) write(1, s, sizeof(s) - 1); |
|
|
|
|
#define WRITE_D(s) write(1, s, string_length(s)); |
|
|
|
|
|
|
|
|
|
#define PROMPT_LENGTH 255 |
|
|
|
|
|
|
|
|
|
@ -20,54 +18,50 @@ static char prompt[PROMPT_LENGTH + 1]; |
|
|
|
|
static uint8_t prompt_length = 0; |
|
|
|
|
static uint8_t prompt_offset = 0; |
|
|
|
|
|
|
|
|
|
process_t *proc; |
|
|
|
|
|
|
|
|
|
static uint8_t active = 1; |
|
|
|
|
typedef void (*app_t)(uint8_t argc, char **argv); |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
const char *name; |
|
|
|
|
app_t app; |
|
|
|
|
} app_entry_t; |
|
|
|
|
|
|
|
|
|
static app_entry_t apps[] = { |
|
|
|
|
static app_entry_t builtins[] = { |
|
|
|
|
{"help", help}, |
|
|
|
|
{"cd", cd}, |
|
|
|
|
{"ls", ls}, |
|
|
|
|
{"cat", cat}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void help(process_t *proc, uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
if (argc > 1) { |
|
|
|
|
WRITE_S("help: accepts no arguments\n"); |
|
|
|
|
static void help(uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
if (argc) { |
|
|
|
|
WRITE_S("help: expects no arguments"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
WRITE_S("Available commands:\n"); |
|
|
|
|
for (uint64_t i = 0; i < sizeof(apps) / sizeof(app_entry_t); i++) { |
|
|
|
|
WRITE_D(apps[i].name); |
|
|
|
|
for (uint64_t i = 0; i < sizeof(builtins) / sizeof(app_entry_t); i++) { |
|
|
|
|
WRITE_D(builtins[i].name); |
|
|
|
|
WRITE_S("\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cd(process_t *proc, uint8_t argc, char **argv) { |
|
|
|
|
static void cd(uint8_t argc, char **argv) { |
|
|
|
|
if (argc != 2) { |
|
|
|
|
WRITE_S("cd: requires a single path\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
path_t *new = path_open(proc->root, proc->cwd, argv[1]); |
|
|
|
|
if (!new) { |
|
|
|
|
if (chdir(argv[1]) == (uint64_t)-1) { |
|
|
|
|
WRITE_S("cd: path does not exist\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
path_close(proc->cwd); |
|
|
|
|
proc->cwd = new; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void print_prompt() { |
|
|
|
|
WRITE_S("["); |
|
|
|
|
fs_node_t *curr = proc->cwd->depth ? proc->cwd->stack[proc->cwd->depth - 1] : proc->root; |
|
|
|
|
WRITE_D(curr->name); |
|
|
|
|
char path[PROMPT_LENGTH]; |
|
|
|
|
uint8_t pl = getcwd(PROMPT_LENGTH, path); |
|
|
|
|
char *components[16]; |
|
|
|
|
uint8_t cl = string_split(path, '/', 16, components); |
|
|
|
|
|
|
|
|
|
WRITE_S("[") |
|
|
|
|
WRITE_D(pl == 1 ? "/" : components[cl - 1]); |
|
|
|
|
WRITE_S("]$ "); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -76,7 +70,7 @@ static void on_home_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, bs, prompt_offset); |
|
|
|
|
write(1, bs, prompt_offset); |
|
|
|
|
prompt_offset = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -85,7 +79,7 @@ static void on_left_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, bs, 1); |
|
|
|
|
write(1, bs, 1); |
|
|
|
|
prompt_offset--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -94,7 +88,7 @@ static void on_right_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, prompt + prompt_offset, 1); |
|
|
|
|
write(1, prompt + prompt_offset, 1); |
|
|
|
|
prompt_offset++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -103,7 +97,7 @@ static void on_end_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, prompt + prompt_offset, prompt_length - prompt_offset); |
|
|
|
|
write(1, prompt + prompt_offset, prompt_length - prompt_offset); |
|
|
|
|
prompt_offset = prompt_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -116,14 +110,16 @@ static void on_enter_pressed() { |
|
|
|
|
WRITE_S("\n"); |
|
|
|
|
|
|
|
|
|
uint8_t i; |
|
|
|
|
for (i = 0; i < sizeof(apps) / sizeof(app_entry_t); i++) { |
|
|
|
|
if (string_equal(argv[0], apps[i].name)) { |
|
|
|
|
apps[i].app(proc, argc, argv); |
|
|
|
|
for (i = 0; i < sizeof(builtins) / sizeof(app_entry_t); i++) { |
|
|
|
|
if (string_equal(argv[0], builtins[i].name)) { |
|
|
|
|
builtins[i].app(argc, argv); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (i == sizeof(apps) / sizeof(app_entry_t)) { |
|
|
|
|
WRITE_S("Unknown command\n"); |
|
|
|
|
if (i == sizeof(builtins) / sizeof(app_entry_t)) { |
|
|
|
|
if (spawn(argv[0], argc, (const char **)argv) == (uint64_t)-1){ |
|
|
|
|
WRITE_S("terminal: program not found\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
prompt_length = prompt_offset = 0; |
|
|
|
|
print_prompt(); |
|
|
|
|
@ -137,7 +133,7 @@ static void on_cancel_pressed() { |
|
|
|
|
|
|
|
|
|
static void on_disconnect_pressed() { |
|
|
|
|
WRITE_S("^D\n"); |
|
|
|
|
active = 0; |
|
|
|
|
exit(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_ctrl_character_pressed(char c) { |
|
|
|
|
@ -150,9 +146,9 @@ static void on_ctrl_character_pressed(char c) { |
|
|
|
|
|
|
|
|
|
static void redraw_from_cursor() { |
|
|
|
|
uint64_t tail = prompt_length - prompt_offset; |
|
|
|
|
proc->stdout->write(proc->stdout, prompt + prompt_offset, tail); |
|
|
|
|
proc->stdout->write(proc->stdout, ws, 1); // erase the character past the end
|
|
|
|
|
proc->stdout->write(proc->stdout, bs, tail + 1); // move back to cursor position
|
|
|
|
|
write(1, prompt + prompt_offset, tail); |
|
|
|
|
write(1, ws, 1); // erase the character past the end
|
|
|
|
|
write(1, bs, tail + 1); // move back to cursor position
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_character_pressed(char c) { |
|
|
|
|
@ -166,7 +162,7 @@ static void on_character_pressed(char c) { |
|
|
|
|
prompt_length++; |
|
|
|
|
prompt_offset++; |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, &c, 1); // emit the character itself
|
|
|
|
|
write(1, &c, 1); // emit the character itself
|
|
|
|
|
redraw_from_cursor(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -180,7 +176,7 @@ static void on_backspace_pressed() { |
|
|
|
|
prompt_offset--; |
|
|
|
|
prompt_length--; |
|
|
|
|
|
|
|
|
|
proc->stdout->write(proc->stdout, bs, 1); |
|
|
|
|
write(1, bs, 1); |
|
|
|
|
redraw_from_cursor(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -262,22 +258,20 @@ static void on_char_received(char c) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void terminal(process_t *p, __attribute__((unused)) uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
int main() { |
|
|
|
|
memory_set('\b', PROMPT_LENGTH, (char *)bs); |
|
|
|
|
memory_set(' ', PROMPT_LENGTH, (char *)ws); |
|
|
|
|
|
|
|
|
|
proc = p; |
|
|
|
|
|
|
|
|
|
WRITE_D("Welcome to FreywarOS v" VERSION "!\n\n"); |
|
|
|
|
|
|
|
|
|
print_prompt(); |
|
|
|
|
|
|
|
|
|
while (active) { |
|
|
|
|
while (1) { |
|
|
|
|
char c; |
|
|
|
|
if (proc->stdin->read(proc->stdin, 1, &c)) { |
|
|
|
|
if (read(0, 1, &c)) { |
|
|
|
|
on_char_received(c); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc = NUL; |
|
|
|
|
return 0; |
|
|
|
|
} |