[Finsh] Add features to execute module.

This commit is contained in:
bernard 2014-01-03 08:01:24 +08:00
parent bd8fc8b2f9
commit 1f8a0668d2
1 changed files with 334 additions and 260 deletions

View File

@ -24,21 +24,26 @@
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2013-03-30 Bernard the first verion for FinSH * 2013-03-30 Bernard the first verion for finsh
* 2014-01-03 Bernard msh can execute module.
*/ */
#include "msh.h" #include "msh.h"
#include <finsh.h> #include <finsh.h>
#include <shell.h> #include <shell.h>
#define RT_FINSH_ARG_MAX 10 #ifdef RT_USING_DFS
#include <dfs_posix.h>
#endif
#define RT_FINSH_ARG_MAX 10
typedef int (*cmd_function_t)(int argc, char** argv); typedef int (*cmd_function_t)(int argc, char** argv);
#ifdef FINSH_USING_MSH #ifdef FINSH_USING_MSH
#ifdef FINSH_USING_MSH_ONLY #ifdef FINSH_USING_MSH_ONLY
rt_bool_t msh_is_used(void) rt_bool_t msh_is_used(void)
{ {
return RT_TRUE; return RT_TRUE;
} }
#else #else
#ifdef FINSH_USING_MSH_DEFAULT #ifdef FINSH_USING_MSH_DEFAULT
@ -48,351 +53,420 @@ static rt_bool_t __msh_state = RT_FALSE;
#endif #endif
rt_bool_t msh_is_used(void) rt_bool_t msh_is_used(void)
{ {
return __msh_state; return __msh_state;
} }
static int msh_exit(int argc, char** argv) static int msh_exit(int argc, char** argv)
{ {
/* return to finsh shell mode */ /* return to finsh shell mode */
__msh_state = RT_FALSE; __msh_state = RT_FALSE;
return 0; return 0;
} }
FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.); FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.);
static int msh_enter(void) static int msh_enter(void)
{ {
/* enter module shell mode */ /* enter module shell mode */
__msh_state = RT_TRUE; __msh_state = RT_TRUE;
return 0; return 0;
} }
FINSH_FUNCTION_EXPORT_ALIAS(msh_enter, msh, use module shell); FINSH_FUNCTION_EXPORT_ALIAS(msh_enter, msh, use module shell);
#endif #endif
int msh_help(int argc, char** argv) int msh_help(int argc, char** argv)
{ {
rt_kprintf("RT-Thread shell commands:\n"); rt_kprintf("RT-Thread shell commands:\n");
{ {
struct finsh_syscall *index; struct finsh_syscall *index;
for (index = _syscall_table_begin; for (index = _syscall_table_begin;
index < _syscall_table_end; index < _syscall_table_end;
FINSH_NEXT_SYSCALL(index)) FINSH_NEXT_SYSCALL(index))
{ {
if (strncmp(index->name, "__cmd_", 6) != 0) continue; if (strncmp(index->name, "__cmd_", 6) != 0) continue;
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB) #if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
rt_kprintf("%-16s - %s\n", &index->name[6], index->desc); rt_kprintf("%-16s - %s\n", &index->name[6], index->desc);
#else #else
rt_kprintf("%s ", &index->name[6]); rt_kprintf("%s ", &index->name[6]);
#endif #endif
} }
} }
rt_kprintf("\n"); rt_kprintf("\n");
return 0; return 0;
} }
FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, RT-Thread shell help.); FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, RT-Thread shell help.);
static int msh_split(char* cmd, rt_size_t length, char* argv[RT_FINSH_ARG_MAX]) static int msh_split(char* cmd, rt_size_t length, char* argv[RT_FINSH_ARG_MAX])
{ {
char *ptr; char *ptr;
rt_size_t position; rt_size_t position;
rt_size_t argc; rt_size_t argc;
ptr = cmd; ptr = cmd;
position = 0; argc = 0; position = 0; argc = 0;
while (position < length) while (position < length)
{ {
/* strip bank and tab */ /* strip bank and tab */
while ((*ptr == ' ' || *ptr == '\t') && position < length) while ((*ptr == ' ' || *ptr == '\t') && position < length)
{ {
*ptr = '\0'; *ptr = '\0';
ptr ++; position ++; ptr ++; position ++;
} }
if (position >= length) break; if (position >= length) break;
/* handle string */ /* handle string */
if (*ptr == '"') if (*ptr == '"')
{ {
ptr ++; position ++; ptr ++; position ++;
argv[argc] = ptr; argc ++; argv[argc] = ptr; argc ++;
/* skip this string */ /* skip this string */
while (*ptr != '"' && position < length) while (*ptr != '"' && position < length)
{ {
if (*ptr == '\\') if (*ptr == '\\')
{ {
if (*(ptr + 1) == '"') if (*(ptr + 1) == '"')
{ {
ptr ++; position ++; ptr ++; position ++;
} }
} }
ptr ++; position ++; ptr ++; position ++;
} }
if (position >= length) break; if (position >= length) break;
/* skip '"' */ /* skip '"' */
*ptr = '\0'; ptr ++; position ++; *ptr = '\0'; ptr ++; position ++;
} }
else else
{ {
argv[argc] = ptr; argv[argc] = ptr;
argc ++; argc ++;
while ((*ptr != ' ' && *ptr != '\t') && position < length) while ((*ptr != ' ' && *ptr != '\t') && position < length)
{ {
ptr ++; position ++; ptr ++; position ++;
} }
if (position >= length) break; if (position >= length) break;
} }
} }
return argc; return argc;
} }
static cmd_function_t msh_get_cmd(char *cmd) static cmd_function_t msh_get_cmd(char *cmd)
{ {
struct finsh_syscall *index; struct finsh_syscall *index;
cmd_function_t cmd_func = RT_NULL; cmd_function_t cmd_func = RT_NULL;
for (index = _syscall_table_begin; for (index = _syscall_table_begin;
index < _syscall_table_end; index < _syscall_table_end;
FINSH_NEXT_SYSCALL(index)) FINSH_NEXT_SYSCALL(index))
{ {
if (strncmp(index->name, "__cmd_", 6) != 0) continue; if (strncmp(index->name, "__cmd_", 6) != 0) continue;
if (strcmp(&index->name[6], cmd) == 0) if (strcmp(&index->name[6], cmd) == 0)
{ {
cmd_func = (cmd_function_t)index->func; cmd_func = (cmd_function_t)index->func;
break; break;
} }
} }
return cmd_func; return cmd_func;
} }
#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
int msh_exec_module(int argc, char** argv)
{
int fd = -1;
char *pg_name;
int length, cmd_length;
if (argc == 0) return -RT_ERROR; /* no command */
/* get name length */
cmd_length = rt_strlen(argv[0]); length = cmd_length + 32;
pg_name = (char*) rt_malloc(length);
if (pg_name == RT_NULL) return -RT_ENOMEM; /* no memory */
if (strstr(argv[0], ".mo") != RT_NULL || strstr(argv[0], ".MO") != RT_NULL)
{
/* try to open program */
if (fd < 0)
{
rt_snprintf(pg_name, length - 1, "%s", argv[0]);
fd = open(pg_name, O_RDONLY, 0);
}
/* search in /bin path */
if (fd < 0)
{
rt_snprintf(pg_name, length - 1, "/bin/%s", argv[0]);
fd = open(pg_name, O_RDONLY, 0);
}
}
else
{
/* add .mo and open program */
/* try to open program */
if (fd < 0)
{
rt_snprintf(pg_name, length - 1, "%s.mo", argv[0]);
fd = open(pg_name, O_RDONLY, 0);
}
/* search in /bin path */
if (fd < 0)
{
rt_snprintf(pg_name, length - 1, "/bin/%s.mo", argv[0]);
fd = open(pg_name, O_RDONLY, 0);
}
}
if (fd >= 0)
{
/* found program */
close(fd);
rt_module_open(pg_name);
}
else
{
rt_kprintf("%s: program not found.\n", argv[0]);
}
rt_free(pg_name);
return 0;
}
#endif
int msh_exec(char* cmd, rt_size_t length) int msh_exec(char* cmd, rt_size_t length)
{ {
int argc; int argc;
char *argv[RT_FINSH_ARG_MAX]; char *argv[RT_FINSH_ARG_MAX];
cmd_function_t cmd_func; cmd_function_t cmd_func;
memset(argv, 0x00, sizeof(argv)); memset(argv, 0x00, sizeof(argv));
argc = msh_split(cmd, length, argv); argc = msh_split(cmd, length, argv);
if (argc == 0) return -1; if (argc == 0) return -1;
/* get command in internal commands */ /* get command in internal commands */
cmd_func = msh_get_cmd(argv[0]); cmd_func = msh_get_cmd(argv[0]);
if (cmd_func == RT_NULL) if (cmd_func == RT_NULL)
{ {
rt_kprintf("%s: command not found\n", argv[0]); #ifdef RT_USING_MODULE
return -1; msh_exec_module(argc, argv);
} #else
rt_kprintf("%s: command not found.\n", argv[0]);
#endif
return -1;
}
/* exec this command */ /* exec this command */
return cmd_func(argc, argv); return cmd_func(argc, argv);
} }
static int str_common(const char *str1, const char *str2) static int str_common(const char *str1, const char *str2)
{ {
const char *str = str1; const char *str = str1;
while ((*str != 0) && (*str2 != 0) && (*str == *str2)) while ((*str != 0) && (*str2 != 0) && (*str == *str2))
{ {
str ++; str ++;
str2 ++; str2 ++;
} }
return (str - str1); return (str - str1);
} }
#ifdef RT_USING_DFS #ifdef RT_USING_DFS
#include <dfs_posix.h>
void msh_auto_complete_path(char *path) void msh_auto_complete_path(char *path)
{ {
DIR* dir; DIR* dir;
struct dirent *dirent; struct dirent *dirent;
char *full_path, *ptr, *index; char *full_path, *ptr, *index;
full_path = (char*)rt_malloc(256); full_path = (char*)rt_malloc(256);
if (full_path == RT_NULL) return; /* out of memory */ if (full_path == RT_NULL) return; /* out of memory */
ptr = full_path; ptr = full_path;
if (*path != '/') if (*path != '/')
{ {
getcwd(full_path, 256); getcwd(full_path, 256);
if (full_path[rt_strlen(full_path) - 1] != '/') if (full_path[rt_strlen(full_path) - 1] != '/')
strcat(full_path, "/"); strcat(full_path, "/");
} }
else *full_path = '\0'; else *full_path = '\0';
index = RT_NULL; ptr = path; index = RT_NULL; ptr = path;
for (;;) for (;;)
{ {
if (*ptr == '/') index = ptr + 1; if (!*ptr) break; ptr ++; if (*ptr == '/') index = ptr + 1; if (!*ptr) break; ptr ++;
} }
if (index == RT_NULL) index = path; if (index == RT_NULL) index = path;
if (index != RT_NULL) if (index != RT_NULL)
{ {
char *dest = index; char *dest = index;
/* fill the parent path */ /* fill the parent path */
ptr = full_path; ptr = full_path;
while (*ptr) ptr ++; while (*ptr) ptr ++;
for (index = path; index != dest;) for (index = path; index != dest;)
*ptr++ = *index++; *ptr++ = *index++;
*ptr = '\0'; *ptr = '\0';
dir = opendir(full_path); dir = opendir(full_path);
if (dir == RT_NULL) /* open directory failed! */ if (dir == RT_NULL) /* open directory failed! */
{ {
rt_free(full_path); rt_free(full_path);
return; return;
} }
/* restore the index position */ /* restore the index position */
index = dest; index = dest;
} }
/* auto complete the file or directory name */ /* auto complete the file or directory name */
if (*index == '\0') /* display all of files and directories */ if (*index == '\0') /* display all of files and directories */
{ {
for (;;) for (;;)
{ {
dirent = readdir(dir); dirent = readdir(dir);
if (dirent == RT_NULL) break; if (dirent == RT_NULL) break;
rt_kprintf("%s\n", dirent->d_name); rt_kprintf("%s\n", dirent->d_name);
} }
} }
else else
{ {
int length, min_length; int length, min_length;
min_length = 0; min_length = 0;
for (;;) for (;;)
{ {
dirent = readdir(dir); dirent = readdir(dir);
if (dirent == RT_NULL) break; if (dirent == RT_NULL) break;
/* matched the prefix string */ /* matched the prefix string */
if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
{ {
if (min_length == 0) if (min_length == 0)
{ {
min_length = rt_strlen(dirent->d_name); min_length = rt_strlen(dirent->d_name);
/* save dirent name */ /* save dirent name */
strcpy(full_path, dirent->d_name); strcpy(full_path, dirent->d_name);
} }
length = str_common(dirent->d_name, full_path); length = str_common(dirent->d_name, full_path);
if (length < min_length) if (length < min_length)
{ {
min_length = length; min_length = length;
} }
} }
} }
if (min_length) if (min_length)
{ {
if (min_length < rt_strlen(full_path)) if (min_length < rt_strlen(full_path))
{ {
/* list the candidate */ /* list the candidate */
rewinddir(dir); rewinddir(dir);
for (;;) for (;;)
{ {
dirent = readdir(dir); dirent = readdir(dir);
if (dirent == RT_NULL) break; if (dirent == RT_NULL) break;
if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
rt_kprintf("%s\n", dirent->d_name); rt_kprintf("%s\n", dirent->d_name);
} }
} }
length = index - path; length = index - path;
memcpy(index, full_path, min_length); memcpy(index, full_path, min_length);
path[length + min_length] = '\0'; path[length + min_length] = '\0';
} }
} }
closedir(dir); closedir(dir);
rt_free(full_path); rt_free(full_path);
} }
#endif #endif
void msh_auto_complete(char *prefix) void msh_auto_complete(char *prefix)
{ {
int length, min_length; int length, min_length;
const char *name_ptr, *cmd_name; const char *name_ptr, *cmd_name;
struct finsh_syscall *index; struct finsh_syscall *index;
min_length = 0; min_length = 0;
name_ptr = RT_NULL; name_ptr = RT_NULL;
if (*prefix == '\0') if (*prefix == '\0')
{ {
msh_help(0, RT_NULL); msh_help(0, RT_NULL);
return; return;
} }
#ifdef RT_USING_DFS #ifdef RT_USING_DFS
/* check whether a spare in the command */ /* check whether a spare in the command */
{ {
char *ptr; char *ptr;
ptr = prefix + rt_strlen(prefix); ptr = prefix + rt_strlen(prefix);
while (ptr != prefix) while (ptr != prefix)
{ {
if (*ptr == ' ') if (*ptr == ' ')
{ {
msh_auto_complete_path(ptr + 1); msh_auto_complete_path(ptr + 1);
break; break;
} }
ptr --; ptr --;
} }
} }
#endif #endif
/* checks in internal command */ /* checks in internal command */
{ {
for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index)) for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
{ {
/* skip finsh shell function */ /* skip finsh shell function */
if (strncmp(index->name, "__cmd_", 6) != 0) continue; if (strncmp(index->name, "__cmd_", 6) != 0) continue;
cmd_name = (const char*) &index->name[6]; cmd_name = (const char*) &index->name[6];
if (strncmp(prefix, cmd_name, strlen(prefix)) == 0) if (strncmp(prefix, cmd_name, strlen(prefix)) == 0)
{ {
if (min_length == 0) if (min_length == 0)
{ {
/* set name_ptr */ /* set name_ptr */
name_ptr = cmd_name; name_ptr = cmd_name;
/* set initial length */ /* set initial length */
min_length = strlen(name_ptr); min_length = strlen(name_ptr);
} }
length = str_common(name_ptr, cmd_name); length = str_common(name_ptr, cmd_name);
if (length < min_length) if (length < min_length)
min_length = length; min_length = length;
rt_kprintf("%s\n", cmd_name); rt_kprintf("%s\n", cmd_name);
} }
} }
} }
/* auto complete string */ /* auto complete string */
if (name_ptr != NULL) if (name_ptr != NULL)
{ {
rt_strncpy(prefix, name_ptr, min_length); rt_strncpy(prefix, name_ptr, min_length);
} }
return ; return ;
} }
#endif #endif