|
|
|
|
@ -3,14 +3,17 @@ |
|
|
|
|
#include "src/app/ls.h" |
|
|
|
|
#include "src/fs.h" |
|
|
|
|
#include "src/memory.h" |
|
|
|
|
#include "src/path.h" |
|
|
|
|
#include "src/process.h" |
|
|
|
|
#include "src/string.h" |
|
|
|
|
#include "src/util.h" |
|
|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
#define PROMPT_LENGTH 255 |
|
|
|
|
static void help(process_t *proc, uint8_t argc, char **argv); |
|
|
|
|
static void cd(process_t *proc, uint8_t argc, char **argv); |
|
|
|
|
|
|
|
|
|
fs_node_t *root; |
|
|
|
|
#define PROMPT_LENGTH 255 |
|
|
|
|
|
|
|
|
|
static const char bs[PROMPT_LENGTH + 1]; |
|
|
|
|
static const char ws[PROMPT_LENGTH + 1]; |
|
|
|
|
@ -19,20 +22,63 @@ static char prompt[PROMPT_LENGTH + 1]; |
|
|
|
|
static uint8_t prompt_length = 0; |
|
|
|
|
static uint8_t prompt_offset = 0; |
|
|
|
|
|
|
|
|
|
static stream_t *stream_in; |
|
|
|
|
static stream_t *stream_out; |
|
|
|
|
process_t *proc; |
|
|
|
|
|
|
|
|
|
static uint8_t active = 1; |
|
|
|
|
|
|
|
|
|
#define WRITE_S(s) stream_out->write(stream_out, s, sizeof(s) - 1); |
|
|
|
|
#define WRITE_D(s) stream_out->write(stream_out, s, string_length(s)); |
|
|
|
|
typedef struct { |
|
|
|
|
const char *name; |
|
|
|
|
app_t app; |
|
|
|
|
} app_entry_t; |
|
|
|
|
|
|
|
|
|
static app_entry_t apps[] = { |
|
|
|
|
{"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"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
WRITE_S("Available commands:\n"); |
|
|
|
|
for (uint64_t i = 0; i < sizeof(apps) / sizeof(app_entry_t); i++) { |
|
|
|
|
WRITE_D(apps[i].name); |
|
|
|
|
WRITE_S("\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cd(process_t *proc, 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) { |
|
|
|
|
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); |
|
|
|
|
WRITE_S("]$ "); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_home_pressed() { |
|
|
|
|
if (!prompt_offset) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, bs, prompt_offset); |
|
|
|
|
proc->stdout->write(proc->stdout, bs, prompt_offset); |
|
|
|
|
prompt_offset = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -41,7 +87,7 @@ static void on_left_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, bs, 1); |
|
|
|
|
proc->stdout->write(proc->stdout, bs, 1); |
|
|
|
|
prompt_offset--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -50,7 +96,7 @@ static void on_right_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, prompt + prompt_offset, 1); |
|
|
|
|
proc->stdout->write(proc->stdout, prompt + prompt_offset, 1); |
|
|
|
|
prompt_offset++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -59,21 +105,10 @@ static void on_end_pressed() { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, prompt + prompt_offset, prompt_length - prompt_offset); |
|
|
|
|
proc->stdout->write(proc->stdout, prompt + prompt_offset, prompt_length - prompt_offset); |
|
|
|
|
prompt_offset = prompt_length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void help(uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
if (argc > 1) { |
|
|
|
|
WRITE_S("help: accepts no arguments\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
WRITE_S("Available commands:\n" |
|
|
|
|
"help\n" |
|
|
|
|
"ls DIR\n" |
|
|
|
|
"cat FILE\n") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_enter_pressed() { |
|
|
|
|
prompt[prompt_length] = '\0'; |
|
|
|
|
|
|
|
|
|
@ -82,23 +117,24 @@ static void on_enter_pressed() { |
|
|
|
|
|
|
|
|
|
WRITE_S("\n"); |
|
|
|
|
|
|
|
|
|
if (string_equal(argv[0], "help")) { |
|
|
|
|
help(argc, argv); |
|
|
|
|
} else if (string_equal(argv[0], "ls")) { |
|
|
|
|
ls(stream_in, stream_out, argc, argv); |
|
|
|
|
} else if (string_equal(argv[0], "cat")) { |
|
|
|
|
cat(stream_in, stream_out, argc, argv); |
|
|
|
|
} else { |
|
|
|
|
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); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (i == sizeof(apps) / sizeof(app_entry_t)) { |
|
|
|
|
WRITE_S("Unknown command\n"); |
|
|
|
|
} |
|
|
|
|
WRITE_S("$ "); |
|
|
|
|
prompt_length = prompt_offset = 0; |
|
|
|
|
print_prompt(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_cancel_pressed() { |
|
|
|
|
WRITE_S("^C\n"); |
|
|
|
|
WRITE_S("$ "); |
|
|
|
|
prompt_length = prompt_offset = 0; |
|
|
|
|
print_prompt(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_disconnect_pressed() { |
|
|
|
|
@ -116,9 +152,9 @@ static void on_ctrl_character_pressed(char c) { |
|
|
|
|
|
|
|
|
|
static void redraw_from_cursor() { |
|
|
|
|
uint64_t tail = prompt_length - prompt_offset; |
|
|
|
|
stream_out->write(stream_out, prompt + prompt_offset, tail); |
|
|
|
|
stream_out->write(stream_out, ws, 1); // erase the character past the end
|
|
|
|
|
stream_out->write(stream_out, bs, tail + 1); // move back to cursor position
|
|
|
|
|
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
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_character_pressed(char c) { |
|
|
|
|
@ -132,7 +168,7 @@ static void on_character_pressed(char c) { |
|
|
|
|
prompt_length++; |
|
|
|
|
prompt_offset++; |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, &c, 1); // emit the character itself
|
|
|
|
|
proc->stdout->write(proc->stdout, &c, 1); // emit the character itself
|
|
|
|
|
redraw_from_cursor(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -146,7 +182,7 @@ static void on_backspace_pressed() { |
|
|
|
|
prompt_offset--; |
|
|
|
|
prompt_length--; |
|
|
|
|
|
|
|
|
|
stream_out->write(stream_out, bs, 1); |
|
|
|
|
proc->stdout->write(proc->stdout, bs, 1); |
|
|
|
|
redraw_from_cursor(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -228,28 +264,24 @@ static void on_char_received(char c) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void terminal(stream_t *stdin, stream_t *stdout, __attribute__((unused)) uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
void terminal(process_t *p, __attribute__((unused)) uint8_t argc, __attribute__((unused)) char **argv) { |
|
|
|
|
memory_set('\b', PROMPT_LENGTH, (char *)bs); |
|
|
|
|
memory_set(' ', PROMPT_LENGTH, (char *)ws); |
|
|
|
|
|
|
|
|
|
stream_in = stdin; |
|
|
|
|
stream_out = stdout; |
|
|
|
|
|
|
|
|
|
root = fs_mount(); |
|
|
|
|
proc = p; |
|
|
|
|
|
|
|
|
|
char *greeting = string_format("Welcome to FreywarOS v%s!\n\n", VERSION); |
|
|
|
|
WRITE_D(greeting); |
|
|
|
|
memory_free(greeting); |
|
|
|
|
|
|
|
|
|
WRITE_S("$ "); |
|
|
|
|
print_prompt(); |
|
|
|
|
|
|
|
|
|
while (active) { |
|
|
|
|
char c; |
|
|
|
|
if (stream_in->read(stream_in, 1, &c)) { |
|
|
|
|
if (proc->stdin->read(proc->stdin, 1, &c)) { |
|
|
|
|
on_char_received(c); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// fs_unmount(root);
|
|
|
|
|
stream_in = stream_out = NUL; |
|
|
|
|
proc = NUL; |
|
|
|
|
} |
|
|
|
|
|