All checks were successful
Build documentation / build-and-deploy (push) Successful in 2m38s
227 lines
5.2 KiB
C
227 lines
5.2 KiB
C
#include <desc.h>
|
|
#include <liballoc.h>
|
|
#include <list.h>
|
|
#include <minmax.h>
|
|
#include <path.h>
|
|
#include <printf.h>
|
|
#include <process.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <str_status.h>
|
|
#include <string.h>
|
|
#include <system.h>
|
|
#include <terminal_cursor.h>
|
|
|
|
#define LINE_BUFFER_MAX 1024
|
|
#define TOKEN_MAX 64
|
|
#define PROMPT "ce $ "
|
|
|
|
struct token {
|
|
struct list_node_link tokens_link;
|
|
char buffer[TOKEN_MAX];
|
|
};
|
|
|
|
static int e_pid;
|
|
static int e_pgid;
|
|
|
|
static bool run = true;
|
|
|
|
static void putch (char ch) { mail_send (e_pgid, &ch, 1); }
|
|
void putchar_ (char ch) { putch (ch); }
|
|
|
|
static bool tokenize_line (void* ctx, const char* start, size_t len) {
|
|
struct list_node_link** head = ctx;
|
|
|
|
struct token* token = malloc (sizeof (*token));
|
|
|
|
if (token == NULL)
|
|
return false;
|
|
|
|
memset (token, 0, sizeof (*token));
|
|
memcpy (token->buffer, start, min (sizeof (token->buffer) - 1, len));
|
|
|
|
list_append ((*head), &token->tokens_link);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void free_tokens (struct list_node_link* tokens) {
|
|
struct list_node_link *token_link, *token_tmp_link;
|
|
list_foreach (tokens, token_link, token_tmp_link) {
|
|
struct token* token = list_entry (token_link, struct token, tokens_link);
|
|
list_remove (tokens, &token->tokens_link);
|
|
free (token);
|
|
}
|
|
}
|
|
|
|
static void cmd_echo (struct list_node_link* tokens) {
|
|
struct list_node_link *token_link, *token_tmp_link;
|
|
list_foreach (tokens, token_link, token_tmp_link) {
|
|
struct token* token = list_entry (token_link, struct token, tokens_link);
|
|
|
|
printf ("%s ", token->buffer);
|
|
}
|
|
}
|
|
|
|
static void cmd_cat (struct list_node_link* tokens) {
|
|
if (tokens == NULL) {
|
|
printf ("ERROR: no file paths provided\n");
|
|
return;
|
|
}
|
|
|
|
struct desc desc;
|
|
char volume[VOLUME_MAX];
|
|
const char* path;
|
|
int ret;
|
|
|
|
struct list_node_link *token_link, *token_tmp_link;
|
|
list_foreach (tokens, token_link, token_tmp_link) {
|
|
struct token* token = list_entry (token_link, struct token, tokens_link);
|
|
|
|
if (!path_parse (token->buffer, volume, &path)) {
|
|
printf ("ERROR bad path '%s'\n", token->buffer);
|
|
continue;
|
|
}
|
|
|
|
if ((ret = volume_open (volume)) < 0) {
|
|
printf ("ERROR could not open volume '%s': %s\n", volume, str_status[-ret]);
|
|
continue;
|
|
}
|
|
|
|
describe (path, &desc);
|
|
|
|
if (desc.type != FS_FILE)
|
|
goto close;
|
|
|
|
char* buffer = malloc (desc.size + 1);
|
|
|
|
if (buffer == NULL)
|
|
goto close;
|
|
|
|
memset (buffer, 0, desc.size + 1);
|
|
read (path, 0, (uint8_t*)buffer, desc.size);
|
|
printf ("%s\n", buffer);
|
|
|
|
close:
|
|
if (buffer != NULL)
|
|
free (buffer);
|
|
volume_close ();
|
|
}
|
|
}
|
|
|
|
static void cmd_ls (struct list_node_link* tokens) {
|
|
if (tokens == NULL) {
|
|
printf ("ERROR no directory path provided\n");
|
|
return;
|
|
}
|
|
|
|
struct token* token = list_entry (tokens, struct token, tokens_link);
|
|
struct desc desc;
|
|
char volume[VOLUME_MAX];
|
|
const char* path;
|
|
int ret;
|
|
struct dir_entry entry;
|
|
|
|
if (!path_parse (token->buffer, volume, &path)) {
|
|
printf ("ERROR bad path '%s'\n", token->buffer);
|
|
return;
|
|
}
|
|
|
|
if ((ret = volume_open (volume)) < 0) {
|
|
printf ("ERROR could not open volume '%s': %s\n", volume, str_status[-ret]);
|
|
return;
|
|
}
|
|
|
|
describe (path, &desc);
|
|
|
|
if (desc.type != FS_DIR) {
|
|
volume_close ();
|
|
}
|
|
|
|
size_t entries = desc.size;
|
|
for (size_t entry_num = 0; entry_num < entries; entry_num++) {
|
|
read_dir_entry (path, &entry, entry_num);
|
|
describe (entry.path, &desc);
|
|
|
|
printf ("%-40s%c %-40zu\n", entry.path, (desc.type == FS_DIR ? '*' : ' '), desc.size);
|
|
}
|
|
|
|
volume_close ();
|
|
}
|
|
|
|
static void cmd_quit (void) {
|
|
run = false;
|
|
printf ("Goodbye!\n");
|
|
}
|
|
|
|
static void cmd_help (void) {
|
|
printf ("Available commands:\n");
|
|
printf ("echo <word1> <word2> <word3> ...\n");
|
|
printf ("help\n");
|
|
printf ("cat <file path>\n");
|
|
printf ("ls <directory path>\n");
|
|
printf ("quit\n");
|
|
}
|
|
|
|
static void exec_tokens (struct list_node_link* tokens) {
|
|
struct token* cmd_token = list_entry (tokens, struct token, tokens_link);
|
|
|
|
if (strcmp (cmd_token->buffer, "echo") == 0) {
|
|
cmd_echo (tokens->next);
|
|
} else if (strcmp (cmd_token->buffer, "help") == 0) {
|
|
cmd_help ();
|
|
} else if (strcmp (cmd_token->buffer, "cat") == 0) {
|
|
cmd_cat (tokens->next);
|
|
} else if (strcmp (cmd_token->buffer, "ls") == 0) {
|
|
cmd_ls (tokens->next);
|
|
} else if (strcmp (cmd_token->buffer, "quit") == 0) {
|
|
cmd_quit ();
|
|
} else {
|
|
printf ("ERROR: unknown command '%s'\n", cmd_token->buffer);
|
|
}
|
|
}
|
|
|
|
static void exec_line (const char* line) {
|
|
struct list_node_link* tokens = NULL;
|
|
|
|
strtokenize (line, ' ', &tokens, &tokenize_line);
|
|
|
|
if (tokens != NULL)
|
|
exec_tokens (tokens);
|
|
|
|
free_tokens (tokens);
|
|
}
|
|
|
|
void app_main (void) {
|
|
e_pid = get_exec_pid ();
|
|
e_pgid = get_procgroup (e_pid);
|
|
|
|
size_t line_cursor = 0;
|
|
char line_buffer[LINE_BUFFER_MAX + 1];
|
|
memset (line_buffer, 0, sizeof (line_buffer));
|
|
|
|
while (run) {
|
|
printf (PROMPT);
|
|
|
|
char ch = 0;
|
|
for (;;) {
|
|
mail_receive (&ch, 1);
|
|
|
|
if (ch == '\n')
|
|
break;
|
|
|
|
if (line_cursor < LINE_BUFFER_MAX) {
|
|
line_buffer[line_cursor++] = ch;
|
|
printf ("%c", ch);
|
|
}
|
|
}
|
|
|
|
printf ("\n");
|
|
exec_line (line_buffer);
|
|
|
|
line_cursor = 0;
|
|
memset (line_buffer, 0, sizeof (line_buffer));
|
|
}
|
|
}
|