617 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			617 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2006-2018, RT-Thread Development Team
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * SPDX-License-Identifier: Apache-2.0
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Change Logs:
							 | 
						||
| 
								 | 
							
								 * Date           Author       Notes
							 | 
						||
| 
								 | 
							
								 * 2013-03-30     Bernard      the first verion for finsh
							 | 
						||
| 
								 | 
							
								 * 2014-01-03     Bernard      msh can execute module.
							 | 
						||
| 
								 | 
							
								 * 2017-07-19     Aubr.Cool    limit argc to RT_FINSH_ARG_MAX
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#include <rtthread.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef FINSH_USING_MSH
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "msh.h"
							 | 
						||
| 
								 | 
							
								#include <finsh.h>
							 | 
						||
| 
								 | 
							
								#include <shell.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_DFS
							 | 
						||
| 
								 | 
							
								#include <dfs_posix.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_MODULE
							 | 
						||
| 
								 | 
							
								#include <dlmodule.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef FINSH_ARG_MAX
							 | 
						||
| 
								 | 
							
								#define FINSH_ARG_MAX    8
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef int (*cmd_function_t)(int argc, char **argv);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef FINSH_USING_MSH
							 | 
						||
| 
								 | 
							
								#ifdef FINSH_USING_MSH_ONLY
							 | 
						||
| 
								 | 
							
								rt_bool_t msh_is_used(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return RT_TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#ifdef FINSH_USING_MSH_DEFAULT
							 | 
						||
| 
								 | 
							
								static rt_bool_t __msh_state = RT_TRUE;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								static rt_bool_t __msh_state = RT_FALSE;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								rt_bool_t msh_is_used(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return __msh_state;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int msh_exit(int argc, char **argv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /* return to finsh shell mode */
							 | 
						||
| 
								 | 
							
								    __msh_state = RT_FALSE;
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int msh_enter(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /* enter module shell mode */
							 | 
						||
| 
								 | 
							
								    __msh_state = RT_TRUE;
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								FINSH_FUNCTION_EXPORT_ALIAS(msh_enter, msh, use module shell);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int msh_help(int argc, char **argv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    rt_kprintf("RT-Thread shell commands:\n");
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        struct finsh_syscall *index;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (index = _syscall_table_begin;
							 | 
						||
| 
								 | 
							
								                index < _syscall_table_end;
							 | 
						||
| 
								 | 
							
								                FINSH_NEXT_SYSCALL(index))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (strncmp(index->name, "__cmd_", 6) != 0) continue;
							 | 
						||
| 
								 | 
							
								#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
							 | 
						||
| 
								 | 
							
								            rt_kprintf("%-16s - %s\n", &index->name[6], index->desc);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            rt_kprintf("%s ", &index->name[6]);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    rt_kprintf("\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, RT-Thread shell help.);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int msh_split(char *cmd, rt_size_t length, char *argv[FINSH_ARG_MAX])
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    char *ptr;
							 | 
						||
| 
								 | 
							
								    rt_size_t position;
							 | 
						||
| 
								 | 
							
								    rt_size_t argc;
							 | 
						||
| 
								 | 
							
								    rt_size_t i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ptr = cmd;
							 | 
						||
| 
								 | 
							
								    position = 0; argc = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (position < length)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* strip bank and tab */
							 | 
						||
| 
								 | 
							
								        while ((*ptr == ' ' || *ptr == '\t') && position < length)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            *ptr = '\0';
							 | 
						||
| 
								 | 
							
								            ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if(argc >= FINSH_ARG_MAX)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            rt_kprintf("Too many args ! We only Use:\n");
							 | 
						||
| 
								 | 
							
								            for(i = 0; i < argc; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                rt_kprintf("%s ", argv[i]);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            rt_kprintf("\n");
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (position >= length) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* handle string */
							 | 
						||
| 
								 | 
							
								        if (*ptr == '"')
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								            argv[argc] = ptr; argc ++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /* skip this string */
							 | 
						||
| 
								 | 
							
								            while (*ptr != '"' && position < length)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (*ptr == '\\')
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    if (*(ptr + 1) == '"')
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (position >= length) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /* skip '"' */
							 | 
						||
| 
								 | 
							
								            *ptr = '\0'; ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            argv[argc] = ptr;
							 | 
						||
| 
								 | 
							
								            argc ++;
							 | 
						||
| 
								 | 
							
								            while ((*ptr != ' ' && *ptr != '\t') && position < length)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                ptr ++; position ++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (position >= length) break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return argc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static cmd_function_t msh_get_cmd(char *cmd, int size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct finsh_syscall *index;
							 | 
						||
| 
								 | 
							
								    cmd_function_t cmd_func = RT_NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (index = _syscall_table_begin;
							 | 
						||
| 
								 | 
							
								            index < _syscall_table_end;
							 | 
						||
| 
								 | 
							
								            FINSH_NEXT_SYSCALL(index))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (strncmp(index->name, "__cmd_", 6) != 0) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (strncmp(&index->name[6], cmd, size) == 0 &&
							 | 
						||
| 
								 | 
							
								                index->name[6 + size] == '\0')
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            cmd_func = (cmd_function_t)index->func;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return cmd_func;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
							 | 
						||
| 
								 | 
							
								/* Return 0 on module executed. Other value indicate error.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								int msh_exec_module(const char *cmd_line, int size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int ret;
							 | 
						||
| 
								 | 
							
								    int fd = -1;
							 | 
						||
| 
								 | 
							
								    char *pg_name;
							 | 
						||
| 
								 | 
							
								    int length, cmd_length = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (size == 0)
							 | 
						||
| 
								 | 
							
								        return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								    /* get the length of command0 */
							 | 
						||
| 
								 | 
							
								    while ((cmd_line[cmd_length] != ' ' && cmd_line[cmd_length] != '\t') && cmd_length < size)
							 | 
						||
| 
								 | 
							
								        cmd_length ++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* get name length */
							 | 
						||
| 
								 | 
							
								    length = cmd_length + 32;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* allocate program name memory */
							 | 
						||
| 
								 | 
							
								    pg_name = (char *) rt_malloc(length);
							 | 
						||
| 
								 | 
							
								    if (pg_name == RT_NULL)
							 | 
						||
| 
								 | 
							
								        return -RT_ENOMEM;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* 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 */
							 | 
						||
| 
								 | 
							
								        fd = open(pg_name, O_RDONLY, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* search in /bin path */
							 | 
						||
| 
								 | 
							
								        if (fd < 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            rt_snprintf(pg_name, length - 1, "/bin/%.*s", cmd_length, cmd_line);
							 | 
						||
| 
								 | 
							
								            fd = open(pg_name, O_RDONLY, 0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* add .mo and open program */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* try to open program */
							 | 
						||
| 
								 | 
							
								        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", cmd_length, cmd_line);
							 | 
						||
| 
								 | 
							
								            fd = open(pg_name, O_RDONLY, 0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (fd >= 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        /* found program */
							 | 
						||
| 
								 | 
							
								        close(fd);
							 | 
						||
| 
								 | 
							
								        dlmodule_exec(pg_name, cmd_line, size);
							 | 
						||
| 
								 | 
							
								        ret = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        ret = -1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rt_free(pg_name);
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int system(const char *command)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int ret = -RT_ENOMEM;
							 | 
						||
| 
								 | 
							
								    char *cmd = rt_strdup(command);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (cmd)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        ret = msh_exec(cmd, rt_strlen(cmd));
							 | 
						||
| 
								 | 
							
								        rt_free(cmd);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								RTM_EXPORT(system);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int _msh_exec_cmd(char *cmd, rt_size_t length, int *retp)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int argc;
							 | 
						||
| 
								 | 
							
								    rt_size_t cmd0_size = 0;
							 | 
						||
| 
								 | 
							
								    cmd_function_t cmd_func;
							 | 
						||
| 
								 | 
							
								    char *argv[FINSH_ARG_MAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    RT_ASSERT(cmd);
							 | 
						||
| 
								 | 
							
								    RT_ASSERT(retp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* find the size of first command */
							 | 
						||
| 
								 | 
							
								    while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
							 | 
						||
| 
								 | 
							
								        cmd0_size ++;
							 | 
						||
| 
								 | 
							
								    if (cmd0_size == 0)
							 | 
						||
| 
								 | 
							
								        return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    cmd_func = msh_get_cmd(cmd, cmd0_size);
							 | 
						||
| 
								 | 
							
								    if (cmd_func == RT_NULL)
							 | 
						||
| 
								 | 
							
								        return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* split arguments */
							 | 
						||
| 
								 | 
							
								    memset(argv, 0x00, sizeof(argv));
							 | 
						||
| 
								 | 
							
								    argc = msh_split(cmd, length, argv);
							 | 
						||
| 
								 | 
							
								    if (argc == 0)
							 | 
						||
| 
								 | 
							
								        return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* exec this command */
							 | 
						||
| 
								 | 
							
								    *retp = cmd_func(argc, argv);
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(RT_USING_LWP) && defined(RT_USING_DFS)
							 | 
						||
| 
								 | 
							
								static int _msh_exec_lwp(char *cmd, rt_size_t length)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int argc;
							 | 
						||
| 
								 | 
							
								    int cmd0_size = 0;
							 | 
						||
| 
								 | 
							
								    char *argv[FINSH_ARG_MAX];
							 | 
						||
| 
								 | 
							
								    int fd = -1;
							 | 
						||
| 
								 | 
							
								    char *pg_name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    extern int exec(char*, int, char**);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* find the size of first command */
							 | 
						||
| 
								 | 
							
								    while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
							 | 
						||
| 
								 | 
							
								        cmd0_size ++;
							 | 
						||
| 
								 | 
							
								    if (cmd0_size == 0)
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* split arguments */
							 | 
						||
| 
								 | 
							
								    rt_memset(argv, 0x00, sizeof(argv));
							 | 
						||
| 
								 | 
							
								    argc = msh_split(cmd, length, argv);
							 | 
						||
| 
								 | 
							
								    if (argc == 0)
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pg_name = argv[0];
							 | 
						||
| 
								 | 
							
								    /* try to open program */
							 | 
						||
| 
								 | 
							
								    fd = open(pg_name, O_RDONLY, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (fd < 0)
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* found program */
							 | 
						||
| 
								 | 
							
								    close(fd);
							 | 
						||
| 
								 | 
							
								    exec(pg_name, argc, argv);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int msh_exec(char *cmd, rt_size_t length)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int cmd_ret;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* strim the beginning of command */
							 | 
						||
| 
								 | 
							
								    while (*cmd  == ' ' || *cmd == '\t')
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        cmd++;
							 | 
						||
| 
								 | 
							
								        length--;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (length == 0)
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* Exec sequence:
							 | 
						||
| 
								 | 
							
								     * 1. built-in command
							 | 
						||
| 
								 | 
							
								     * 2. module(if enabled)
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    if (_msh_exec_cmd(cmd, length, &cmd_ret) == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return cmd_ret;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_DFS
							 | 
						||
| 
								 | 
							
								#ifdef DFS_USING_WORKDIR
							 | 
						||
| 
								 | 
							
								    if (msh_exec_script(cmd, length) == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_MODULE
							 | 
						||
| 
								 | 
							
								    if (msh_exec_module(cmd, length) == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_LWP
							 | 
						||
| 
								 | 
							
								    if (_msh_exec_lwp(cmd, length) == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* truncate the cmd at the first space. */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        char *tcmd;
							 | 
						||
| 
								 | 
							
								        tcmd = cmd;
							 | 
						||
| 
								 | 
							
								        while (*tcmd != ' ' && *tcmd != '\0')
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            tcmd++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        *tcmd = '\0';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    rt_kprintf("%s: command not found.\n", cmd);
							 | 
						||
| 
								 | 
							
								    return -1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int str_common(const char *str1, const char *str2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    const char *str = str1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while ((*str != 0) && (*str2 != 0) && (*str == *str2))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        str ++;
							 | 
						||
| 
								 | 
							
								        str2 ++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (str - str1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_DFS
							 | 
						||
| 
								 | 
							
								void msh_auto_complete_path(char *path)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    DIR *dir = RT_NULL;
							 | 
						||
| 
								 | 
							
								    struct dirent *dirent = RT_NULL;
							 | 
						||
| 
								 | 
							
								    char *full_path, *ptr, *index;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!path)
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    full_path = (char *)rt_malloc(256);
							 | 
						||
| 
								 | 
							
								    if (full_path == RT_NULL) return; /* out of memory */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (*path != '/')
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        getcwd(full_path, 256);
							 | 
						||
| 
								 | 
							
								        if (full_path[rt_strlen(full_path) - 1]  != '/')
							 | 
						||
| 
								 | 
							
								            strcat(full_path, "/");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else *full_path = '\0';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    index = RT_NULL;
							 | 
						||
| 
								 | 
							
								    ptr = path;
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (*ptr == '/') index = ptr + 1;
							 | 
						||
| 
								 | 
							
								        if (!*ptr) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        ptr ++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (index == RT_NULL) index = path;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (index != RT_NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        char *dest = index;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* fill the parent path */
							 | 
						||
| 
								 | 
							
								        ptr = full_path;
							 | 
						||
| 
								 | 
							
								        while (*ptr) ptr ++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (index = path; index != dest;)
							 | 
						||
| 
								 | 
							
								            *ptr++ = *index++;
							 | 
						||
| 
								 | 
							
								        *ptr = '\0';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dir = opendir(full_path);
							 | 
						||
| 
								 | 
							
								        if (dir == RT_NULL) /* open directory failed! */
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            rt_free(full_path);
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* restore the index position */
							 | 
						||
| 
								 | 
							
								        index = dest;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* auto complete the file or directory name */
							 | 
						||
| 
								 | 
							
								    if (*index == '\0') /* display all of files and directories */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dirent = readdir(dir);
							 | 
						||
| 
								 | 
							
								            if (dirent == RT_NULL) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            rt_kprintf("%s\n", dirent->d_name);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        rt_size_t length, min_length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        min_length = 0;
							 | 
						||
| 
								 | 
							
								        for (;;)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dirent = readdir(dir);
							 | 
						||
| 
								 | 
							
								            if (dirent == RT_NULL) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /* matched the prefix string */
							 | 
						||
| 
								 | 
							
								            if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (min_length == 0)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    min_length = rt_strlen(dirent->d_name);
							 | 
						||
| 
								 | 
							
								                    /* save dirent name */
							 | 
						||
| 
								 | 
							
								                    strcpy(full_path, dirent->d_name);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                length = str_common(dirent->d_name, full_path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (length < min_length)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    min_length = length;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (min_length)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (min_length < rt_strlen(full_path))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                /* list the candidate */
							 | 
						||
| 
								 | 
							
								                rewinddir(dir);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                for (;;)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    dirent = readdir(dir);
							 | 
						||
| 
								 | 
							
								                    if (dirent == RT_NULL) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
							 | 
						||
| 
								 | 
							
								                        rt_kprintf("%s\n", dirent->d_name);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            length = index - path;
							 | 
						||
| 
								 | 
							
								            memcpy(index, full_path, min_length);
							 | 
						||
| 
								 | 
							
								            path[length + min_length] = '\0';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    closedir(dir);
							 | 
						||
| 
								 | 
							
								    rt_free(full_path);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void msh_auto_complete(char *prefix)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int length, min_length;
							 | 
						||
| 
								 | 
							
								    const char *name_ptr, *cmd_name;
							 | 
						||
| 
								 | 
							
								    struct finsh_syscall *index;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    min_length = 0;
							 | 
						||
| 
								 | 
							
								    name_ptr = RT_NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (*prefix == '\0')
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        msh_help(0, RT_NULL);
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_DFS
							 | 
						||
| 
								 | 
							
								    /* check whether a spare in the command */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        char *ptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        ptr = prefix + rt_strlen(prefix);
							 | 
						||
| 
								 | 
							
								        while (ptr != prefix)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if (*ptr == ' ')
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                msh_auto_complete_path(ptr + 1);
							 | 
						||
| 
								 | 
							
								                break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            ptr --;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_MODULE
							 | 
						||
| 
								 | 
							
								        /* There is a chance that the user want to run the module directly. So
							 | 
						||
| 
								 | 
							
								         * try to complete the file names. If the completed path is not a
							 | 
						||
| 
								 | 
							
								         * module, the system won't crash anyway. */
							 | 
						||
| 
								 | 
							
								        if (ptr == prefix)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            msh_auto_complete_path(ptr);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* checks in internal command */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            /* skip finsh shell function */
							 | 
						||
| 
								 | 
							
								            if (strncmp(index->name, "__cmd_", 6) != 0) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            cmd_name = (const char *) &index->name[6];
							 | 
						||
| 
								 | 
							
								            if (strncmp(prefix, cmd_name, strlen(prefix)) == 0)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (min_length == 0)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    /* set name_ptr */
							 | 
						||
| 
								 | 
							
								                    name_ptr = cmd_name;
							 | 
						||
| 
								 | 
							
								                    /* set initial length */
							 | 
						||
| 
								 | 
							
								                    min_length = strlen(name_ptr);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                length = str_common(name_ptr, cmd_name);
							 | 
						||
| 
								 | 
							
								                if (length < min_length)
							 | 
						||
| 
								 | 
							
								                    min_length = length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                rt_kprintf("%s\n", cmd_name);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* auto complete string */
							 | 
						||
| 
								 | 
							
								    if (name_ptr != NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        rt_strncpy(prefix, name_ptr, min_length);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return ;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* FINSH_USING_MSH */
							 |