Files
mop3/ce/ce.c
kamkow1 02e77b5c90
All checks were successful
Build documentation / build-and-deploy (push) Successful in 2m36s
CE interactive shell
2026-02-21 22:14:16 +01:00

179 lines
4.0 KiB
C

#include <liballoc.h>
#include <list.h>
#include <m/fs_desc_buffer.h>
#include <minmax.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 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 fs_desc_buffer desc;
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);
int ret;
ret = open (token->buffer);
if (ret < 0) {
printf ("ERROR opening %s: %s\n", token->buffer, str_status[-ret]);
continue;
}
describe (token->buffer, &desc);
if (desc.type != FS_FILE)
goto close1;
char* buffer = malloc (desc.size + 1);
if (buffer == NULL)
goto close1;
memset (buffer, 0, desc.size + 1);
ret = read (token->buffer, 0, (uint8_t*)buffer, desc.size);
if (ret < 0) {
printf ("ERROR reading%s: %s\n", token->buffer, str_status[-ret]);
goto close1;
}
printf ("%s\n", buffer);
close1:
if (buffer != NULL)
free (buffer);
close (token->buffer);
}
}
static void cmd_help (struct list_node_link* tokens) {
(void)tokens;
printf ("Available commands:\n");
printf ("\techo <word1> <word2> <word3> ...\n");
printf ("\thelp\n");
printf ("\tcat <file path>\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 (tokens->next);
} else if (strcmp (cmd_token->buffer, "cat") == 0) {
cmd_cat (tokens->next);
} 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));
for (;;) {
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));
printf ("\n");
}
}