[Kernel] application module can support arguments

This commit is contained in:
bernard 2014-01-11 16:33:31 +08:00
parent c07a78ae00
commit 31446eab4c
5 changed files with 304 additions and 45 deletions

View File

@ -155,7 +155,7 @@ static int msh_split(char* cmd, rt_size_t length, char* argv[RT_FINSH_ARG_MAX])
return argc;
}
static cmd_function_t msh_get_cmd(char *cmd)
static cmd_function_t msh_get_cmd(char *cmd, int size)
{
struct finsh_syscall *index;
cmd_function_t cmd_func = RT_NULL;
@ -166,7 +166,7 @@ static cmd_function_t msh_get_cmd(char *cmd)
{
if (strncmp(index->name, "__cmd_", 6) != 0) continue;
if (strcmp(&index->name[6], cmd) == 0)
if (strncmp(&index->name[6], cmd, size) == 0)
{
cmd_func = (cmd_function_t)index->func;
break;
@ -177,33 +177,40 @@ static cmd_function_t msh_get_cmd(char *cmd)
}
#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
int msh_exec_module(int argc, char** argv)
int msh_exec_module(char* cmd_line, int size)
{
int fd = -1;
char *pg_name;
int length, cmd_length;
int length, cmd_length = 0;
if (argc == 0) return -RT_ERROR; /* no command */
if (size == 0) return -RT_ERROR; /* no command */
/* get the length of command0 */
while ((cmd_line[cmd_length] != ' ' && cmd_line[cmd_length] != '\t') && cmd_length < size)
cmd_length ++;
/* get name length */
cmd_length = rt_strlen(argv[0]); length = cmd_length + 32;
length = cmd_length + 32;
/* allocate program name memory */
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)
/* copy command0 */
memcpy(pg_name, cmd_line, cmd_length);
pg_name[cmd_length] = '\0';
if (strstr(pg_name, ".mo") != RT_NULL || strstr(pg_name, ".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]);
rt_snprintf(pg_name, length - 1, "/bin/%.*s", cmd_length, cmd_line);
fd = open(pg_name, O_RDONLY, 0);
}
}
@ -214,14 +221,14 @@ int msh_exec_module(int argc, char** argv)
/* try to open program */
if (fd < 0)
{
rt_snprintf(pg_name, length - 1, "%s.mo", argv[0]);
strcat(pg_name, ".mo");
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]);
rt_snprintf(pg_name, length - 1, "/bin/%.*s.mo", cmd_length, cmd_line);
fd = open(pg_name, O_RDONLY, 0);
}
}
@ -230,11 +237,11 @@ int msh_exec_module(int argc, char** argv)
{
/* found program */
close(fd);
rt_module_open(pg_name);
rt_module_exec_cmd(pg_name, cmd_line, size);
}
else
{
rt_kprintf("%s: program not found.\n", argv[0]);
rt_kprintf("%s: program not found.\n", pg_name);
}
rt_free(pg_name);
@ -247,24 +254,29 @@ int msh_exec(char* cmd, rt_size_t length)
int argc;
char *argv[RT_FINSH_ARG_MAX];
int cmd0_size = 0;
cmd_function_t cmd_func;
memset(argv, 0x00, sizeof(argv));
argc = msh_split(cmd, length, argv);
if (argc == 0) return -1;
while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
cmd0_size ++;
/* get command in internal commands */
cmd_func = msh_get_cmd(argv[0]);
/* try to get built-in command */
cmd_func = msh_get_cmd(cmd, cmd0_size);
if (cmd_func == RT_NULL)
{
#ifdef RT_USING_MODULE
msh_exec_module(argc, argv);
msh_exec_module(cmd, length);
#else
rt_kprintf("%s: command not found.\n", argv[0]);
#endif
return -1;
}
/* split arguments */
memset(argv, 0x00, sizeof(argv));
argc = msh_split(cmd, length, argv);
if (argc == 0) return -1;
/* exec this command */
return cmd_func(argc, argv);
}

View File

@ -622,6 +622,14 @@ RTM_EXPORT(lwip_select);
RTM_EXPORT(lwip_ioctl);
RTM_EXPORT(lwip_fcntl);
RTM_EXPORT(lwip_htons);
RTM_EXPORT(lwip_ntohs);
RTM_EXPORT(lwip_htonl);
RTM_EXPORT(lwip_ntohl);
RTM_EXPORT(ipaddr_aton);
RTM_EXPORT(ipaddr_ntoa);
#if LWIP_DNS
#include <lwip/netdb.h>
RTM_EXPORT(lwip_gethostbyname);

View File

@ -952,10 +952,11 @@ struct rt_module
rt_uint8_t *module_space; /**< module memory space */
void *module_entry; /**< entry address of module's thread */
rt_thread_t module_thread; /**< stack size of module's thread */
rt_uint32_t stack_size; /**< priority of module's thread */
rt_uint32_t thread_priority;
void *module_entry; /**< the entry address of module */
rt_thread_t module_thread; /**< the main thread of module */
rt_uint8_t* module_cmd_line; /**< module command line */
rt_uint32_t module_cmd_size; /**< the size of module command line */
#ifdef RT_USING_SLAB
/* module memory allocator */
@ -964,10 +965,10 @@ struct rt_module
rt_uint32_t page_cnt; /**< module's using pages count */
#endif
rt_uint32_t nsym; /**< number of symbol in the module */
struct rt_module_symtab *symtab; /**< module symbol table */
rt_uint16_t nref; /**< reference count */
rt_uint32_t nref; /**< reference count */
rt_uint16_t nsym; /**< number of symbol in the module */
struct rt_module_symtab *symtab; /**< module symbol table */
/* object in this module, module object is the last basic object type */
struct rt_object_information module_object[RT_Object_Class_Unknown];

View File

@ -420,6 +420,7 @@ rt_module_t rt_module_load(const char *name, void *module_ptr);
rt_err_t rt_module_unload(rt_module_t module);
#ifdef RT_USING_DFS
rt_module_t rt_module_open(const char *filename);
rt_module_t rt_module_exec_cmd(const char *path, char* cmd_line, int size);
#endif
void *rt_module_malloc(rt_size_t size);
void *rt_module_realloc(void *ptr, rt_size_t size);

View File

@ -801,6 +801,10 @@ rt_module_t rt_module_load(const char *name, void *module_ptr)
/* init module object container */
rt_module_init_object_container(module);
/* initialize an empty command */
module->module_cmd_line = RT_NULL;
module->module_cmd_size = 0;
/* increase module reference count */
module->nref ++;
@ -816,18 +820,10 @@ rt_module_t rt_module_load(const char *name, void *module_ptr)
module->page_cnt = 0;
#endif
/* get the main thread stack size */
module->stack_size = 2048;
module->thread_priority = RT_THREAD_PRIORITY_MAX - 2;
/* create module thread */
module->module_thread =
rt_thread_create(name,
(void(*)(void *))module->module_entry,
RT_NULL,
module->stack_size,
module->thread_priority,
10);
module->module_thread = rt_thread_create(name,
(void(*)(void *))module->module_entry, RT_NULL,
2048, RT_THREAD_PRIORITY_MAX - 2, 10);
RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
module->module_entry));
@ -855,6 +851,168 @@ rt_module_t rt_module_load(const char *name, void *module_ptr)
return module;
}
#define RT_MODULE_ARG_MAX 8
static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
{
int argc = 0;
char *ptr = cmd;
while ((ptr - cmd) < length)
{
/* strip bank and tab */
while ((*ptr == ' ' || *ptr == '\t') && (ptr -cmd)< length)
*ptr++ = '\0';
/* check whether it's the end of line */
if ((ptr - cmd)>= length) break;
/* handle string with quote */
if (*ptr == '"')
{
argv[argc++] = ++ptr;
/* skip this string */
while (*ptr != '"' && (ptr-cmd) < length)
if (*ptr ++ == '\\') ptr ++;
if ((ptr - cmd) >= length) break;
/* skip '"' */
*ptr ++ = '\0';
}
else
{
argv[argc++] = ptr;
while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
ptr ++;
}
if (argc >= RT_MODULE_ARG_MAX) break;
}
return argc;
}
/* module main thread entry */
static void module_main_entry(void* parameter)
{
int argc;
char *argv[RT_MODULE_ARG_MAX];
typedef int (*main_func_t)(int argc, char** argv);
rt_module_t module = (rt_module_t) parameter;
if (module == RT_NULL || module->module_cmd_line == RT_NULL) return;
rt_memset(argv, 0x00, sizeof(argv));
argc = _rt_module_split_arg((char*)module->module_cmd_line, module->module_cmd_size, argv);
if (argc == 0) return ;
/* do the main function */
((main_func_t)module->module_entry)(argc, argv);
return;
}
/**
* This function will load a module with a main function from memory and create a
* main thread for it
*
* @param name the name of module, which shall be unique
* @param module_ptr the memory address of module image
* @argc the count of argument
* @argd the argument data, which should be a
*
* @return the module object
*/
rt_module_t rt_module_do_main(const char *name, void *module_ptr, char* cmd_line, int line_size)
{
rt_module_t module;
RT_DEBUG_NOT_IN_INTERRUPT;
RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s ,", name));
/* check ELF header */
if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
{
rt_kprintf("Module: magic error\n");
return RT_NULL;
}
/* check ELF class */
if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
{
rt_kprintf("Module: ELF class error\n");
return RT_NULL;
}
if (elf_module->e_type == ET_REL)
{
module = _load_relocated_object(name, module_ptr);
}
else if (elf_module->e_type == ET_DYN)
{
module = _load_shared_object(name, module_ptr);
}
else
{
rt_kprintf("Module: unsupported excutable program\n");
return RT_NULL;
}
if (module == RT_NULL)
return RT_NULL;
/* init module object container */
rt_module_init_object_container(module);
/* increase module reference count */
module->nref ++;
if (elf_module->e_entry != 0)
{
#ifdef RT_USING_SLAB
/* init module memory allocator */
module->mem_list = RT_NULL;
/* create page array */
module->page_array =
(void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
module->page_cnt = 0;
#endif
/* set module argument */
module->module_cmd_line = (rt_uint8_t*)rt_malloc(line_size + 1);
rt_memcpy(module->module_cmd_line, cmd_line, line_size);
module->module_cmd_line[line_size] = '\0';
module->module_cmd_size = line_size;
/* create module thread */
module->module_thread = rt_thread_create(name,
module_main_entry, module,
2048, RT_THREAD_PRIORITY_MAX - 2, 10);
/* set module id */
module->module_thread->module_id = (void *)module;
module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
/* startup main thread */
rt_thread_startup(module->module_thread);
}
else
{
/* without entry point */
module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
}
#ifdef RT_USING_HOOK
if (rt_module_load_hook != RT_NULL)
{
rt_module_load_hook(module);
}
#endif
return module;
}
#ifdef RT_USING_DFS
#include <dfs_posix.h>
@ -958,9 +1116,82 @@ rt_module_t rt_module_open(const char *path)
return module;
}
/**
* This function will do a excutable program with main function and parameters.
*
* @param path the full path of application module
* @cmd_line the command line of program
* @size the size of command line of program
*
* @return the module object
*/
rt_module_t rt_module_exec_cmd(const char *path, char* cmd_line, int size)
{
struct stat s;
int fd, length;
char *name, *buffer, *offset_ptr;
struct rt_module *module = RT_NULL;
name = buffer = RT_NULL;
RT_DEBUG_NOT_IN_INTERRUPT;
/* check parameters */
RT_ASSERT(path != RT_NULL);
/* get file size */
if (stat(path, &s) !=0)
{
rt_kprintf("Module: access %s failed\n", path);
goto __exit;
}
/* allocate buffer to save program */
offset_ptr = buffer = (char *)rt_malloc(s.st_size);
if (buffer == RT_NULL)
{
rt_kprintf("Module: out of memory\n");
goto __exit;
}
fd = open(path, O_RDONLY, 0);
if (fd < 0)
{
rt_kprintf("Module: open %s failed\n", path);
goto __exit;
}
do
{
length = read(fd, offset_ptr, 4096);
if (length > 0)
{
offset_ptr += length;
}
}while (length > 0);
/* close fd */
close(fd);
if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
{
rt_kprintf("Module: read file failed\n");
goto __exit;
}
/* get module */
name = _module_name(path);
/* execute module */
module = rt_module_do_main(name, (void *)buffer, cmd_line, size);
__exit:
rt_free(buffer);
rt_free(name);
return module;
}
#if defined(RT_USING_FINSH)
#include <finsh.h>
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
#endif
@ -1131,6 +1362,12 @@ rt_err_t rt_module_destroy(rt_module_t module)
rt_timer_delete((rt_timer_t)object);
}
}
/* delete command line */
if (module->module_cmd_line != RT_NULL)
{
rt_free(module->module_cmd_line);
}
}
#ifdef RT_USING_SLAB