Pārlūkot izejas kodu

[Kernel] application module can support arguments

bernard 11 gadi atpakaļ
vecāks
revīzija
31446eab4c

+ 37 - 25
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);

+ 8 - 0
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 <lwip/netdb.h>
 RTM_EXPORT(lwip_gethostbyname);

+ 8 - 7
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];

+ 1 - 0
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);

+ 249 - 12
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