#include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 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_help (struct list_node_link* tokens) { (void)tokens; printf ("Available commands:\n"); printf ("echo ...\n"); printf ("help\n"); printf ("cat \n"); printf ("ls \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 if (strcmp (cmd_token->buffer, "ls") == 0) { cmd_ls (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)); } }