/* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * * 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 the copyright holder 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. */ #include "shmsg.h" #include "securec.h" #include "shcmd.h" #include "show.h" #if (LOSCFG_USE_SHELL == 1) #include "uart.h" #endif #include "los_event.h" #include "los_task.h" EVENT_CB_S g_shellInputEvent; #define SHELL_CMD_MAX_SIZE 64 #define VISIABLE_CHAR(ch) ((ch) > 0x1F && (ch) < 0x7F) UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType) { CmdItemNode *curCmdItem = (CmdItemNode *)NULL; UINT32 len; UINT32 minLen; CmdModInfo *cmdInfo = OsCmdInfoGet(); if ((cmdParsed == NULL) || (cmdType == NULL)) { return OS_INVALID; } len = strlen(cmdType); LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) { if ((len == strlen(curCmdItem->cmd->cmdKey)) && (strncmp((CHAR *)(curCmdItem->cmd->cmdKey), cmdType, len) == 0)) { minLen = (len < CMD_KEY_LEN) ? len : CMD_KEY_LEN; (VOID)memcpy_s((CHAR *)(cmdParsed->cmdKeyword), CMD_KEY_LEN, cmdType, minLen); cmdParsed->cmdType = curCmdItem->cmd->cmdType; return LOS_OK; } } return OS_INVALID; } CHAR *GetCmdName(const CHAR *cmdline, UINT32 len) { UINT32 loop; const CHAR *tmpStr = NULL; BOOL quotes = FALSE; CHAR *cmdName = NULL; if (cmdline == NULL) { return NULL; } cmdName = (CHAR *)malloc(len + 1); if (cmdName == NULL) { PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); return NULL; } /* Scan the 'cmdline' string for command */ /* Notice: Command string must not have any special name */ for (tmpStr = cmdline, loop = 0; (*tmpStr != '\0') && (loop < len); ) { /* If reach a double quotes, switch the quotes matching status */ if (*tmpStr == '\"') { SWITCH_QUOTES_STATUS(quotes); /* Ignore the double quote charactor itself */ tmpStr++; continue; } /* If detected a space which the quotes matching status is false */ /* which said has detected the first space for separator, finish this scan operation */ if ((*tmpStr == ' ') && (QUOTES_STATUS_CLOSE(quotes))) { break; } cmdName[loop] = *tmpStr++; loop++; } cmdName[loop] = '\0'; return cmdName; } UINT32 PreHandleCmdline(const CHAR *input, CHAR **output, UINT32 *outputlen) { UINT32 shiftLen; UINT32 ret; const CHAR *cmdBuf = input; UINT32 cmdBufLen = strlen(cmdBuf); CHAR *shiftStr = (CHAR *)malloc(cmdBufLen + 1); if (shiftStr == NULL) { PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); return SH_NOK; } (VOID)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1); /* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */ ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1); shiftLen = strlen(shiftStr); if ((ret != SH_OK) || (shiftLen == 0)) { ret = SH_NOK; goto END_FREE_SHIFTSTR; } *output = shiftStr; *outputlen = shiftLen; ret = SH_OK; goto END; END_FREE_SHIFTSTR: free(shiftStr); END: return ret; } STATIC VOID ParseAndExecCmdline(CmdParsed *cmdParsed, const CHAR *cmdline, UINT32 len) { INT32 i; UINT32 ret; CHAR *cmdName = NULL; cmdName = GetCmdName(cmdline, len); if (cmdName == NULL) { PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); return; } ret = ShellMsgTypeGet(cmdParsed, cmdName); if (ret != LOS_OK) { PRINTK("%s:command not found\n", cmdName); free(cmdName); return; } ret = OsCmdParse((CHAR *)cmdline, cmdParsed); if (ret != SH_OK) { PRINTK("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__); goto OUT; } (VOID)OsCmdExec(cmdParsed); OUT: for (i = 0; i < cmdParsed->paramCnt; i++) { if (cmdParsed->paramArray[i] != NULL) { free(cmdParsed->paramArray[i]); cmdParsed->paramArray[i] = NULL; } } free(cmdName); } LITE_OS_SEC_TEXT_MINOR VOID ExecCmdline(const CHAR *cmdline) { UINT32 ret; CHAR *output = NULL; UINT32 outputlen; CmdParsed cmdParsed; if (cmdline == NULL) { return; } (VOID)OsShellInit(); /* strip out unnecessary characters */ ret = PreHandleCmdline(cmdline, &output, &outputlen); if (ret == SH_NOK) { return; } (VOID)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed)); ParseAndExecCmdline(&cmdParsed, output, outputlen); free(output); } #if (LOSCFG_USE_SHELL == 1) VOID ShellTaskEntry(VOID) { CHAR buf[SHELL_CMD_MAX_SIZE] = {0}; CHAR *ptr = buf; PRINTK("OHOS # "); while (1) { (VOID)LOS_EventRead(&g_shellInputEvent, 0x1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); while ((*ptr = (UINT8)UartGetc()) != 0 && *ptr != 13) { if (*ptr == '\x03') { /* ctrl + c */ PRINTK("^C\n\rOHOS # "); ptr = buf; break; } if (*ptr == '\b' && ptr != buf) { /* support backspace */ PRINTK("\b \b"); ptr--; break; } if (!VISIABLE_CHAR(*ptr)) { break; } PRINTK("%c", *ptr); if ((ptr - buf) == (sizeof(buf) - 1)) { break; } ptr++; } if (ptr != buf) { if (*ptr == 13 || ((ptr - buf) == (sizeof(buf) - 1))) { *ptr = '\0'; ptr = buf; PRINTK("\n\r"); ExecCmdline(buf); PRINTK("OHOS # "); } } else if (*ptr == 13) { PRINTK("\n\rOHOS # "); } } } LITE_OS_SEC_TEXT_MINOR UINT32 LosShellInit(VOID) { UINT32 ret; UINT32 taskID1; TSK_INIT_PARAM_S task1 = { 0 }; ret = LOS_EventInit(&g_shellInputEvent); if (ret != LOS_OK) { PRINTK("Init shellInputEvent failed! ERROR: 0x%x\n", ret); return ret; } task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ShellTaskEntry; task1.uwStackSize = 0x1000; task1.pcName = "ShellTaskEntry"; task1.usTaskPrio = LOSCFG_SHELL_PRIO; ret = LOS_TaskCreate(&taskID1, &task1); if (ret != LOS_OK) { PRINTK("Create Shell Task failed! ERROR: 0x%x\n", ret); return ret; } return ret; } #endif