shell: reimplementation to improve command handling and to support multiple serial interfaces

tags/0.1.0
S.J.R. van Schaik 7 years ago
parent f04041ae96
commit fa16f60b06
  1. 29
      include/shell.h
  2. 58
      source/main.c
  3. 8
      source/shell/args.c
  4. 97
      source/shell/cmd.c

@ -1,16 +1,25 @@
#pragma once
size_t count_args(char *line);
char **parse_args(char *line, size_t *argc);
struct cmd {
const char *key;
void (* exec)(const char *line);
const char *cmd;
const char *desc;
void (* exec)(FILE *out, const char **argv, size_t argc);
};
struct shell {
char line[128];
struct cmd *cmds;
const char *prompt;
struct usart_console *con;
FILE *fp;
};
void do_flash_cmd(const char *line);
void do_ftl_cmd(const char *line);
void do_mufs_cmd(const char *line);
size_t count_args(const char *line);
char **parse_args(const char *line, size_t *argc);
void cmd_exec(struct cmd *cmds, FILE *out, const char **argv, size_t argc);
void cmd_parse(struct cmd *cmds, FILE *out, const char *line);
void cmd_exec(struct cmd *cmds, const char *line);
void cmd_loop(const char *s);
int shell_init(struct shell *shell, struct cmd *cmds,
struct usart_console *con, const char *prompt);
int shell_parse(struct shell *shell);

@ -10,51 +10,43 @@
#include <libopencm3/stm32/usart.h>
struct usart_console *user_con, *admin_con;
FILE *user_io, *admin_io;
char user_line[128];
char admin_line[128];
struct shell user_shell, admin_shell;
static void do_echo(FILE *out, const char **argv, size_t argc)
{
if (argc < 1)
return;
fprintf(out, "%s\n", argv[0]);
}
struct cmd cmds[] = {
{ "echo", "", do_echo },
{ NULL, NULL, NULL },
};
int main(void)
{
char **argv;
size_t argc, i;
FILE *fp;
rcc_init();
gpio_init();
user_con = console_init(0);
admin_con = console_init(1);
user_io = console_to_fp(user_con);
admin_io = console_to_fp(admin_con);
fprintf(user_io, "TBM-dev (built on " __DATE__ ")\n");
fprintf(admin_io, "TBM-dev (built on " __DATE__ ")\n");
fprintf(admin_io, "Welcome to the administrative interface.\n");
fprintf(user_io, "tbm # ");
fp = console_to_fp(user_con);
fprintf(fp, "TBM-dev (built on " __DATE__ ")\n");
while (1) {
if (console_getline(user_con, user_line, 128) == 0) {
argv = parse_args(user_line, &argc);
for (i = 0; i < argc; ++i) {
fprintf(user_io, "user: %s\n", argv[i]);
fprintf(admin_io, "user: %s\n", argv[i]);
}
free(argv);
*user_line = '\0';
}
fp = console_to_fp(admin_con);
fprintf(fp, "TBM-dev (built on " __DATE__ ")\n");
if (console_getline(admin_con, admin_line, 128) == 0) {
argv = parse_args(admin_line, &argc);
shell_init(&user_shell, cmds, user_con, "tbm $");
shell_init(&admin_shell, cmds, admin_con, "tbm #");
for (i = 0; i < argc; ++i) {
fprintf(admin_io, "admin: %s\n", argv[i]);
fprintf(user_io, "admin: %s\n", argv[i]);
}
free(argv);
*admin_line = '\0';
}
while (1) {
shell_parse(&user_shell);
shell_parse(&admin_shell);
}
return 0;

@ -4,9 +4,9 @@
#include <shell.h>
size_t count_args(char *line)
size_t count_args(const char *line)
{
char *p = line;
const char *p = line;
size_t n = 0;
while (*p != '\0') {
@ -29,11 +29,11 @@ size_t count_args(char *line)
return n;
}
char **parse_args(char *line, size_t *argc)
char **parse_args(const char *line, size_t *argc)
{
char **argv;
char **arg;
char *p = line;
const char *p = line;
char *s;
size_t n;

@ -2,78 +2,67 @@
#include <stdlib.h>
#include <string.h>
#include <console.h>
#include <shell.h>
static int should_exit = 0;
static char buf[128];
static void do_exit(const char *s);
struct cmd main_cmds[] = {
{ "exit", do_exit },
{ "quit", do_exit },
{ "flash", do_flash_cmd },
{ "ftl", do_ftl_cmd },
{ "mufs", do_mufs_cmd },
{ NULL, NULL },
};
static void do_exit(const char *s)
void cmd_exec(struct cmd *cmds, FILE *out, const char **argv, size_t argc)
{
(void)s;
struct cmd *cmd;
should_exit = 1;
if (argc < 1)
return;
for (cmd = cmds; cmd->cmd; ++cmd) {
if (strcmp(cmd->cmd, argv[0]) == 0) {
cmd->exec(out, argv + 1, argc - 1);
break;
}
}
}
static char *prompt(const char *prefix)
void cmd_parse(struct cmd *cmds, FILE *out, const char *line)
{
size_t len;
printf(prefix);
if (!fgets(buf, 128, stdin))
return NULL;
len = strlen(buf);
char **argv;
size_t argc;
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (!(argv = parse_args(line, &argc)))
return;
putchar('\n');
return buf;
cmd_exec(cmds, out, (const char **)argv, argc);
free(argv);
}
void cmd_exec(struct cmd *cmds, const char *line)
int shell_init(struct shell *shell, struct cmd *cmds,
struct usart_console *con, const char *prompt)
{
struct cmd *cmd;
const char *args;
char *key;
size_t n;
if (!shell || !con)
return -1;
n = strcspn(line, " \n");
key = strndup(line, n);
memset(shell->line, '\0', sizeof shell->line);
shell->cmds = cmds;
shell->con = con;
shell->fp = console_to_fp(con);
shell->prompt = prompt;
args = line + n;
args += strspn(args, " \n");
fprintf(shell->fp, "%s ", prompt ? prompt : "#");
for (cmd = cmds; cmd->key; ++cmd) {
if (strcmp(cmd->key, key) == 0) {
cmd->exec(args);
break;
}
}
free(key);
return 0;
}
void cmd_loop(const char *show)
int shell_parse(struct shell *shell)
{
char *line;
int ret;
should_exit = 0;
if (!shell)
return -1;
while (!should_exit) {
line = prompt(show);
cmd_exec(main_cmds, line);
}
if ((ret = console_getline(shell->con, shell->line, sizeof shell->line)) <
0)
return ret;
cmd_parse(shell->cmds, shell->fp, shell->line);
fprintf(shell->fp, "%s ", shell->prompt ? shell->prompt : "#");
*shell->line = '\0';
return 0;
}

Loading…
Cancel
Save