#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 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 ...\n"); printf ("\thelp\n"); printf ("\tcat \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"); } }