You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
689 lines
20 KiB
Plaintext
689 lines
20 KiB
Plaintext
/******************************************************************************
|
|
* file lib/management/cli.c
|
|
* author YuLiang
|
|
* version 1.0.0
|
|
* date 10-Sep-2021
|
|
* brief This file provides all the cli related operation functions.
|
|
*
|
|
******************************************************************************
|
|
* Attention
|
|
*
|
|
* <h2><center>© COPYRIGHT(c) 2021 LandPower</center></h2>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* 3. Neither the name of LandPower nor the names of its contributors may be used to
|
|
* endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
/* Standard includes. */
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <termios.h>
|
|
#include <pthread.h>
|
|
|
|
/* 外部程序库头文件. */
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
|
|
/* User includes. */
|
|
#include "cli.h"
|
|
#include "list.h"
|
|
|
|
/* Private define ------------------------------------------------------------*/
|
|
|
|
/* Private macro -------------------------------------------------------------*/
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
static int32_t _cli_help(const char *cmd_str);
|
|
static int32_t _cli_version(const char *cmd_str);
|
|
static int32_t _cli_exit(const char *cmd_str);
|
|
|
|
/* The definition of the "help" command. This command is always at the front
|
|
of the list of registered commands. */
|
|
static const cli_command_t _cli_cmd_help =
|
|
{
|
|
"help",
|
|
"List all command.",
|
|
_cli_help,
|
|
0
|
|
};
|
|
|
|
static const cli_command_t _cli_cmd_version =
|
|
{
|
|
"version",
|
|
"Show device version information.",
|
|
_cli_version,
|
|
0
|
|
};
|
|
|
|
static const cli_command_t _cli_cmd_exit =
|
|
{
|
|
"exit",
|
|
"Returns the upper-level node.",
|
|
_cli_exit,
|
|
0
|
|
};
|
|
|
|
/* The definition of the list of commands. Commands that are registered are
|
|
added to this list. */
|
|
static cli_node_t _cli_node[CLI_NODE_COUNT] =
|
|
{
|
|
{"common", 0xffff, CLI_NODE_COMMON, {NULL, NULL}},
|
|
{"Username: ", 0, CLI_NODE_PASSWORD, {NULL, NULL}},
|
|
{"config", 0xffff, CLI_NODE_PASSWORD, {NULL, NULL}},
|
|
};
|
|
|
|
/* 保存readline命令行历史的文件. */
|
|
static const char _cli_history_file[128] = "/home/embed/.command_line_history";
|
|
/* 保存readline命令行内容的buf. */
|
|
static char *_cli_cmd_inpurt = NULL;
|
|
/* 当前cli所在的节点. */
|
|
static CLI_NODE_E _cli_now = CLI_NODE_PASSWORD;
|
|
/* 命令行用户链表. */
|
|
static struct list_head _cli_user_list;
|
|
/* cli线程pid. */
|
|
static pthread_t _cli_pid;
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
extern char* version_get();
|
|
extern char* version_date_get();
|
|
|
|
static int8_t _cli_param_num_get(const char *cmd_str);
|
|
static cli_list_item_t *_cli_cmd_search(const char *cmd_str, CLI_NODE_E node);
|
|
|
|
/* Internal functions --------------------------------------------------------*/
|
|
/* 将node节点下的命令复制到cmd_list_new链表中并排序. */
|
|
static int32_t _cli_cmd_copy_for_node(struct list_head *cmd_list_new, CLI_NODE_E node)
|
|
{
|
|
struct list_head *cmd_list = NULL;
|
|
cli_list_item_t *cmd_item = NULL;
|
|
cli_list_item_t *cmd_item_new = NULL;
|
|
cli_list_item_t *cmd_item_temp = NULL;
|
|
cli_list_item_t *cmd_item_next = NULL;
|
|
int32_t rv = E_NONE;
|
|
|
|
cmd_list = &_cli_node[node].list;
|
|
list_for_each_entry(cmd_item, cmd_list, list)
|
|
{
|
|
/* 复制命令 */
|
|
cmd_item_new = XMALLOC(MTYPE_CLI, sizeof(cli_list_item_t));
|
|
if (NULL == cmd_item_new)
|
|
{
|
|
goto CMD_COPY_FOR_NODE_ERROR;
|
|
}
|
|
memcpy(cmd_item_new, cmd_item, sizeof(cli_list_item_t));
|
|
|
|
/* 命令排序 */
|
|
list_for_each_entry_reverse(cmd_item_temp, cmd_list_new, list)
|
|
{
|
|
if (strcmp(cmd_item_new->cmd->cmd_str, cmd_item_temp->cmd->cmd_str) > 0)
|
|
{
|
|
list_add(&cmd_item_new->list, &cmd_item_temp->list);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* 最小的命令放在链表头 */
|
|
if (&cmd_item_temp->list == cmd_list_new)
|
|
{
|
|
list_add(&cmd_item_new->list, &cmd_item_temp->list);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
|
|
/* 错误回滚已经申请的内存 */
|
|
CMD_COPY_FOR_NODE_ERROR:
|
|
list_for_each_entry_safe(cmd_item_temp, cmd_item_next, cmd_list_new, list)
|
|
{
|
|
list_del(&cmd_item_temp->list);
|
|
XFREE(MTYPE_CLI, cmd_item_temp);
|
|
}
|
|
return rv;
|
|
|
|
}
|
|
|
|
/* The callback function tyhat is executed when "help" is entered. This is the
|
|
only default command that is always present. */
|
|
static int32_t _cli_help(const char *cmd_str)
|
|
{
|
|
struct list_head cmd_list_new;
|
|
cli_list_item_t *cmd_item_temp = NULL;
|
|
cli_list_item_t *cmd_item_next = NULL;
|
|
|
|
INIT_LIST_HEAD(&cmd_list_new);
|
|
|
|
/* 复制命令 */
|
|
LD_E_RETURN(DBG_M_CLI, _cli_cmd_copy_for_node(&cmd_list_new, _cli_now));
|
|
LD_E_RETURN(DBG_M_CLI, _cli_cmd_copy_for_node(&cmd_list_new, CLI_NODE_COMMON));
|
|
|
|
/* 打印信息 */
|
|
list_for_each_entry(cmd_item_temp, &cmd_list_new, list)
|
|
{
|
|
printf("%-32s", cmd_item_temp->cmd->cmd_str);
|
|
printf("%s\r\n", cmd_item_temp->cmd->help_str);
|
|
}
|
|
printf("\n");
|
|
|
|
/* 释放内存 */
|
|
list_for_each_entry_safe(cmd_item_temp, cmd_item_next, &cmd_list_new, list)
|
|
{
|
|
list_del(&cmd_item_temp->list);
|
|
XFREE(MTYPE_CLI, cmd_item_temp);
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
static int32_t _cli_version(const char *cmd_str)
|
|
{
|
|
printf("Welcome To Power IoT Application, By LandPower Embed Application Team.\r\n");
|
|
printf("Copyright(c) 2021 LandPower. All rights reserved.\r\n");
|
|
printf("Software version %s, compile time is %s.\r\n\n", version_get(), version_date_get());
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
static int32_t _cli_exit(const char *cmd_str)
|
|
{
|
|
cli_quit_node();
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* Return the number of parameters that follow the command name. */
|
|
static int8_t _cli_param_num_get(const char *cmd_str)
|
|
{
|
|
int8_t num = 0;
|
|
bool is_end = FALSE;
|
|
|
|
/* Count the number of space delimited words in pcCommandString. */
|
|
while(*cmd_str != 0)
|
|
{
|
|
if (' ' == (*cmd_str))
|
|
{
|
|
if (is_end != TRUE)
|
|
{
|
|
num++;
|
|
is_end = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
is_end = FALSE;
|
|
}
|
|
|
|
cmd_str++;
|
|
}
|
|
|
|
/* If the command string ended with spaces, then there will have been too
|
|
many parameters counted. */
|
|
if( is_end == TRUE )
|
|
{
|
|
num--;
|
|
}
|
|
|
|
/* The value returned is one less than the number of space delimited words,
|
|
as the first word should be the command itself. */
|
|
return num;
|
|
}
|
|
|
|
/* 命令行查找 */
|
|
static cli_list_item_t *_cli_cmd_search(const char *cmd_str, CLI_NODE_E node)
|
|
{
|
|
struct list_head *cmd_list = &_cli_node[node].list;
|
|
cli_list_item_t *cmd_item = NULL;
|
|
const char *cmd_str_register = NULL;
|
|
size_t cmd_str_len = 0;
|
|
|
|
/* Search for the command string in the list of registered commands. */
|
|
list_for_each_entry(cmd_item, cmd_list, list)
|
|
{
|
|
cmd_str_register = cmd_item->cmd->cmd_str;
|
|
cmd_str_len = strlen(cmd_str_register);
|
|
|
|
/* To ensure the string lengths match exactly, so as not to pick up
|
|
a sub-string of a longer command, check the byte after the expected
|
|
end of the string is either the end of the string or a space before
|
|
a parameter. */
|
|
if ((cmd_str[cmd_str_len] != ' ') && (cmd_str[cmd_str_len] != 0x00))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (0 == strncmp(cmd_str, cmd_str_register, cmd_str_len))
|
|
{
|
|
return cmd_item;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* 获取命令行前缀 */
|
|
char *_cli_prefix_get(char *host)
|
|
{
|
|
static char buf[100] = {0};
|
|
|
|
if (0xffff == _cli_node[_cli_now].index)
|
|
{
|
|
snprintf(buf, sizeof(buf), "%s(%s)> ", host, _cli_node[_cli_now].name);
|
|
}
|
|
else
|
|
{
|
|
snprintf(buf, sizeof(buf), "%s(%s-%d)> ", host, _cli_node[_cli_now].name, _cli_node[_cli_now].index);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
/* readline初始化 */
|
|
void _cli_readline_init(void)
|
|
{
|
|
/* 修改自己的按键操作. */
|
|
//rl_bind_key('?', (rl_command_func_t *)vtysh_rl_question);
|
|
//rl_bind_key('\t', (rl_command_func_t *)vtysh_rl_completion);
|
|
/* do not append space after completion. It will be appended
|
|
* in new_completion() function explicitly. */
|
|
rl_completion_append_character = '\0';
|
|
|
|
read_history(_cli_history_file);
|
|
}
|
|
|
|
/* 密码处理函数 */
|
|
static int32_t _cli_process_password(const char * const cmd_str)
|
|
{
|
|
static cli_user_t user_login;
|
|
cli_user_t *user = NULL;
|
|
|
|
/* 表示在输入username */
|
|
if (0 == _cli_node[_cli_now].index)
|
|
{
|
|
/* 保存username,并进入输入password模式 */
|
|
_cli_node[_cli_now].index = 1;
|
|
snprintf(_cli_node[_cli_now].name, CLI_NODE_MAME_LEN, "Password: ");
|
|
snprintf(user_login.username, CLI_USERNAME_LEN, "%s", cmd_str);
|
|
|
|
return E_NONE;
|
|
}
|
|
else
|
|
{
|
|
_cli_node[_cli_now].index = 0;
|
|
snprintf(_cli_node[_cli_now].name, CLI_NODE_MAME_LEN, "Username: ");
|
|
|
|
/* 保存password,比较输入正确性 */
|
|
snprintf(user_login.password, CLI_USERNAME_LEN, "%s", cmd_str);
|
|
list_for_each_entry(user, &_cli_user_list, list)
|
|
{
|
|
if (0 == strcmp(user_login.username, user->username)
|
|
&& 0 == strcmp(user_login.password, user->password))
|
|
{
|
|
/* 找到匹配 */
|
|
printf("\r\n\n");
|
|
cli_entry_node(CLI_NODE_CONFIG, 0xffff);
|
|
return E_NONE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
/* 添加一个新用户 */
|
|
int32_t _cli_user_add(const cli_user_t* const user)
|
|
{
|
|
cli_user_t *user_new = NULL;
|
|
|
|
user_new = XMALLOC(MTYPE_CLI, sizeof(cli_user_t));
|
|
if (NULL == user_new)
|
|
{
|
|
return E_MEM;
|
|
}
|
|
memcpy(user_new, user, sizeof(cli_user_t));
|
|
|
|
list_add(&user_new->list, &_cli_user_list);
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
void *_cli_handle(void *arg)
|
|
{
|
|
char *cmd = NULL;
|
|
|
|
/* 主循环 */
|
|
for(;;)
|
|
{
|
|
/* 输入命令. */
|
|
cmd = cli_shell_gets();
|
|
if (NULL == cmd)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* 执行命令. */
|
|
cli_process_command(cmd);
|
|
}
|
|
}
|
|
|
|
/* Interface functions -------------------------------------------------------*/
|
|
/* description: 命令行注册函数.
|
|
param: cmd -- 要注册的命令行结构体
|
|
node -- 要注册到的节点
|
|
return: E_NONE -- OK
|
|
其他 -- ERROR */
|
|
int32_t cli_register_command(const cli_command_t* const cmd, CLI_NODE_E node)
|
|
{
|
|
struct list_head *cmd_list = &_cli_node[node].list;
|
|
cli_list_item_t *cmd_item = NULL;
|
|
|
|
/* Check the parameter is not NULL. */
|
|
if (NULL == cmd)
|
|
{
|
|
return E_NULL;
|
|
}
|
|
|
|
/* Create a new list item that will reference the command being registered. */
|
|
cmd_item = XMALLOC(MTYPE_CLI, sizeof(cli_list_item_t));
|
|
if (NULL == cmd_item)
|
|
{
|
|
return E_MEM;
|
|
}
|
|
|
|
/* Reference the command being registered from the newly created list item. */
|
|
cmd_item->cmd = cmd;
|
|
|
|
/* The new list item will get added to the end of the list. */
|
|
list_add(&cmd_item->list, cmd_list);
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* description: 命令行注册函数.
|
|
param: cmd_str -- 要执行的命令行
|
|
return: E_NONE -- OK
|
|
其他 -- ERROR */
|
|
int32_t cli_process_command(const char * const cmd_str)
|
|
{
|
|
static const cli_list_item_t *cmd_item = NULL;
|
|
int32_t rv = E_NONE;
|
|
|
|
/* 输入密码的过程不同于执行命令的过程 */
|
|
if (CLI_NODE_PASSWORD == _cli_now)
|
|
{
|
|
if (_cli_process_password(cmd_str) != E_NONE)
|
|
{
|
|
printf("Username or password is not match!!!\r\n\n");
|
|
return E_NOT_FOUND;
|
|
}
|
|
return E_NONE;
|
|
}
|
|
|
|
cmd_item = _cli_cmd_search(cmd_str, (CLI_NODE_E)_cli_now);
|
|
if (NULL == cmd_item)
|
|
{
|
|
cmd_item = _cli_cmd_search(cmd_str, CLI_NODE_COMMON);
|
|
}
|
|
|
|
/* The command has been found. Check it has the expected
|
|
number of parameters. If cExpectedNumberOfParameters is -1,
|
|
then there could be a variable number of parameters and no
|
|
check is made. */
|
|
if (cmd_item != NULL)
|
|
{
|
|
if (cmd_item->cmd->param_num >= 0
|
|
&& _cli_param_num_get(cmd_str) > cmd_item->cmd->param_num )
|
|
{
|
|
rv = E_BAD_PARAM;
|
|
}
|
|
}
|
|
|
|
if ((cmd_item != NULL) && (rv != E_NONE))
|
|
{
|
|
/* The command was found, but the number of parameters with the command
|
|
was incorrect. */
|
|
printf("%s", cli_param_erro);
|
|
cmd_item = NULL;
|
|
}
|
|
else if(cmd_item != NULL)
|
|
{
|
|
/* Call the callback function that is registered to this command. */
|
|
rv = cmd_item->cmd->function(cmd_str);
|
|
if (rv != E_NONE)
|
|
{
|
|
printf("Command(%s) return %d.\r\n\n", cmd_item->cmd->cmd_str, rv);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* pxCommand was NULL, the command was not found. */
|
|
printf("Command not recognised.\r\n\n");
|
|
rv = E_NOT_FOUND;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* description: 进入命令行节点.
|
|
param: cmd_str -- 命令字符串
|
|
param_index -- 需要获取的参数索引
|
|
param_len -- 获取的参数长度
|
|
return: char* -- 获取的参数字符串 */
|
|
const char *cli_parameter_get(const char *cmd_str, int32_t param_index, OUT int32_t *param_len)
|
|
{
|
|
int32_t index = 0;
|
|
const char *param_str = NULL;
|
|
|
|
*param_len = 0;
|
|
|
|
while(index < param_index)
|
|
{
|
|
/* Index the character pointer past the current word. If this is the start
|
|
of the command string then the first word is the command itself. */
|
|
while(((*cmd_str) != 0x00 ) && ((*cmd_str) != ' '))
|
|
{
|
|
cmd_str++;
|
|
}
|
|
|
|
/* Find the start of the next string. */
|
|
while(((*cmd_str) != 0x00) && (' ' == (*cmd_str)))
|
|
{
|
|
cmd_str++;
|
|
}
|
|
|
|
/* Was a string found? */
|
|
if (*cmd_str != 0x00)
|
|
{
|
|
/* Is this the start of the required parameter? */
|
|
index++;
|
|
|
|
if (index == param_index)
|
|
{
|
|
/* How long is the parameter? */
|
|
param_str = cmd_str;
|
|
while(((*cmd_str) != 0x00 ) && ((*cmd_str) != ' '))
|
|
{
|
|
(*param_len)++;
|
|
cmd_str++;
|
|
}
|
|
|
|
if (*param_len == 0 || *param_len >= CLI_PARAM_LEN)
|
|
{
|
|
param_str = NULL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return param_str;
|
|
}
|
|
|
|
/* description: 进入命令行节点.
|
|
param: node -- 节点号
|
|
index -- 节点内部索引
|
|
return: E_NONE -- OK
|
|
其他 -- ERROR */
|
|
int32_t cli_entry_node(CLI_NODE_E node, int16_t index)
|
|
{
|
|
if (node >= CLI_NODE_COUNT)
|
|
{
|
|
return E_BAD_PARAM;
|
|
}
|
|
|
|
_cli_now = node;
|
|
_cli_node[_cli_now].index = index;
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* description: 返回上一级节点.
|
|
param:
|
|
return: */
|
|
void cli_quit_node(void)
|
|
{
|
|
_cli_now = _cli_node[_cli_now].upper_node;
|
|
}
|
|
|
|
/* description: 命令行读取.
|
|
param:
|
|
return: char* -- 读取的一行命令 */
|
|
char *cli_shell_gets(void)
|
|
{
|
|
HIST_ENTRY *last = NULL;
|
|
struct termios new_setting,init_setting;
|
|
|
|
/* readline要求自己释放其返回的buf. */
|
|
if (_cli_cmd_inpurt)
|
|
{
|
|
free(_cli_cmd_inpurt);
|
|
_cli_cmd_inpurt = NULL;
|
|
}
|
|
|
|
/* 获取一行命令. */
|
|
if (CLI_NODE_PASSWORD == _cli_now)
|
|
{
|
|
/* 如果是输入密码则关闭回显. */
|
|
if (1 == _cli_node[_cli_now].index)
|
|
{
|
|
tcgetattr(0, &init_setting);
|
|
new_setting = init_setting;
|
|
new_setting.c_lflag &= ~ECHO;
|
|
tcsetattr(0,TCSANOW,&new_setting);
|
|
}
|
|
|
|
_cli_cmd_inpurt = readline(_cli_node[_cli_now].name);
|
|
|
|
if (1 == _cli_node[_cli_now].index)
|
|
{
|
|
tcsetattr(0,TCSANOW,&init_setting);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_cli_cmd_inpurt = readline(_cli_prefix_get("Power_IoT"));
|
|
/* 如果命令有效记录历史. */
|
|
if (_cli_cmd_inpurt && *_cli_cmd_inpurt)
|
|
{
|
|
using_history();
|
|
last = previous_history();
|
|
if (!last || strcmp (last->line, _cli_cmd_inpurt) != 0)
|
|
{
|
|
add_history(_cli_cmd_inpurt);
|
|
append_history(1, _cli_history_file);
|
|
}
|
|
}
|
|
}
|
|
|
|
//if (strlen(_cli_cmd_inpurt) > 0)
|
|
//{
|
|
// log_warn(LOG_CLI, "\"%s\" is input.", _cli_cmd_inpurt);
|
|
//}
|
|
|
|
return _cli_cmd_inpurt;
|
|
}
|
|
|
|
/* description: 命令行初始函数.
|
|
param:
|
|
return: */
|
|
int32_t cli_init(void)
|
|
{
|
|
struct sched_param param;
|
|
pthread_attr_t attr;
|
|
cli_user_t user_default;
|
|
int32_t i = 0;
|
|
int32_t rv = 0;
|
|
|
|
/* 初始化readline */
|
|
_cli_readline_init();
|
|
|
|
/* 初始化命令节点数据链表 */
|
|
for(i = 0; i < CLI_NODE_COUNT; i++)
|
|
{
|
|
INIT_LIST_HEAD(&_cli_node[i].list);
|
|
}
|
|
|
|
/* 注册公有命令 */
|
|
cli_register_command(&_cli_cmd_help, CLI_NODE_COMMON);
|
|
cli_register_command(&_cli_cmd_version, CLI_NODE_COMMON);
|
|
cli_register_command(&_cli_cmd_exit, CLI_NODE_COMMON);
|
|
|
|
/* 初始化用户列表 */
|
|
INIT_LIST_HEAD(&_cli_user_list);
|
|
|
|
/* 添加默认用户 */
|
|
memset(&user_default, 0, sizeof(cli_user_t));
|
|
snprintf(user_default.username, CLI_USERNAME_LEN, CLI_USERNAME_DEFAULT);
|
|
snprintf(user_default.password, CLI_USERNAME_LEN, CLI_PASSWORD_DEFAULT);
|
|
_cli_user_add(&user_default);
|
|
|
|
/* 配置线程RR调度,优先级50 */
|
|
pthread_attr_init(&attr);
|
|
param.sched_priority = 10;
|
|
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
|
|
rv = pthread_create(&_cli_pid, &attr, _cli_handle, NULL);
|
|
if (rv != 0)
|
|
{
|
|
DBG(DBG_M_CLI, "Can't create pthread %d\r\n", rv);
|
|
}
|
|
else
|
|
{
|
|
thread_m_add("CLI", _cli_pid);
|
|
}
|
|
pthread_attr_destroy(&attr);
|
|
|
|
return E_NONE;
|
|
}
|
|
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/
|