From 31446eab4c01fc7382ad7cd6363c253852ec1235 Mon Sep 17 00:00:00 2001 From: bernard Date: Sat, 11 Jan 2014 16:33:31 +0800 Subject: [PATCH] [Kernel] application module can support arguments --- components/finsh/msh.c | 62 +++-- components/net/lwip-1.4.1/src/arch/sys_arch.c | 8 + include/rtdef.h | 15 +- include/rtthread.h | 1 + src/module.c | 261 +++++++++++++++++- 5 files changed, 303 insertions(+), 44 deletions(-) diff --git a/components/finsh/msh.c b/components/finsh/msh.c index b6ebdf2ac9..8da80fad5b 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -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,27 +221,27 @@ 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); } } - + if (fd >= 0) { /* 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,23 +254,28 @@ 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]); - if (cmd_func == RT_NULL) - { + /* 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]); + rt_kprintf("%s: command not found.\n", argv[0]); #endif - return -1; - } + 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); diff --git a/components/net/lwip-1.4.1/src/arch/sys_arch.c b/components/net/lwip-1.4.1/src/arch/sys_arch.c index 958803f156..ee1d952410 100644 --- a/components/net/lwip-1.4.1/src/arch/sys_arch.c +++ b/components/net/lwip-1.4.1/src/arch/sys_arch.c @@ -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 RTM_EXPORT(lwip_gethostbyname); diff --git a/include/rtdef.h b/include/rtdef.h index e21bc4eb41..3c91ae7d8d 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -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]; diff --git a/include/rtthread.h b/include/rtthread.h index 0891ed9bcc..7704abf208 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -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); diff --git a/src/module.c b/src/module.c index ac689dbade..ec5ed3f7d0 100644 --- a/src/module.c +++ b/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 @@ -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_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 -- GitLab