[Kernel] application module can support arguments
This commit is contained in:
parent
c07a78ae00
commit
31446eab4c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
261
src/module.c
261
src/module.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue