shell: reimplementation to improve command handling and to support multiple serial interfaces
This commit is contained in:
parent
f04041ae96
commit
fa16f60b06
4 changed files with 98 additions and 108 deletions
|
@ -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");
|
||||
|
||||
fp = console_to_fp(admin_con);
|
||||
fprintf(fp, "TBM-dev (built on " __DATE__ ")\n");
|
||||
|
||||
shell_init(&user_shell, cmds, user_con, "tbm $");
|
||||
shell_init(&admin_shell, cmds, admin_con, "tbm #");
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
if (console_getline(admin_con, admin_line, 128) == 0) {
|
||||
argv = parse_args(admin_line, &argc);
|
||||
|
||||
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';
|
||||
}
|
||||
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)s;
|
||||
|
||||
should_exit = 1;
|
||||
}
|
||||
|
||||
static char *prompt(const char *prefix)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
printf(prefix);
|
||||
|
||||
if (!fgets(buf, 128, stdin))
|
||||
return NULL;
|
||||
|
||||
len = strlen(buf);
|
||||
|
||||
if (len > 0 && buf[len - 1] == '\n')
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
putchar('\n');
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cmd_exec(struct cmd *cmds, const char *line)
|
||||
void cmd_exec(struct cmd *cmds, FILE *out, const char **argv, size_t argc)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
const char *args;
|
||||
char *key;
|
||||
size_t n;
|
||||
|
||||
n = strcspn(line, " \n");
|
||||
key = strndup(line, n);
|
||||
if (argc < 1)
|
||||
return;
|
||||
|
||||
args = line + n;
|
||||
args += strspn(args, " \n");
|
||||
|
||||
for (cmd = cmds; cmd->key; ++cmd) {
|
||||
if (strcmp(cmd->key, key) == 0) {
|
||||
cmd->exec(args);
|
||||
for (cmd = cmds; cmd->cmd; ++cmd) {
|
||||
if (strcmp(cmd->cmd, argv[0]) == 0) {
|
||||
cmd->exec(out, argv + 1, argc - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(key);
|
||||
}
|
||||
|
||||
void cmd_loop(const char *show)
|
||||
void cmd_parse(struct cmd *cmds, FILE *out, const char *line)
|
||||
{
|
||||
char *line;
|
||||
char **argv;
|
||||
size_t argc;
|
||||
|
||||
should_exit = 0;
|
||||
if (!(argv = parse_args(line, &argc)))
|
||||
return;
|
||||
|
||||
while (!should_exit) {
|
||||
line = prompt(show);
|
||||
cmd_exec(main_cmds, line);
|
||||
}
|
||||
cmd_exec(cmds, out, (const char **)argv, argc);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
int shell_init(struct shell *shell, struct cmd *cmds,
|
||||
struct usart_console *con, const char *prompt)
|
||||
{
|
||||
if (!shell || !con)
|
||||
return -1;
|
||||
|
||||
memset(shell->line, '\0', sizeof shell->line);
|
||||
shell->cmds = cmds;
|
||||
shell->con = con;
|
||||
shell->fp = console_to_fp(con);
|
||||
shell->prompt = prompt;
|
||||
|
||||
fprintf(shell->fp, "%s ", prompt ? prompt : "#");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shell_parse(struct shell *shell)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!shell)
|
||||
return -1;
|
||||
|
||||
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…
Add table
Add a link
Reference in a new issue