1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "shmsg.h" 33#include "securec.h" 34#include "shcmd.h" 35#include "show.h" 36#if (LOSCFG_USE_SHELL == 1) 37#include "uart.h" 38#endif 39#include "los_event.h" 40#include "los_task.h" 41 42EVENT_CB_S g_shellInputEvent; 43#define SHELL_CMD_MAX_SIZE 64 44 45#define VISIABLE_CHAR(ch) ((ch) > 0x1F && (ch) < 0x7F) 46 47UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType) 48{ 49 CmdItemNode *curCmdItem = (CmdItemNode *)NULL; 50 UINT32 len; 51 UINT32 minLen; 52 CmdModInfo *cmdInfo = OsCmdInfoGet(); 53 54 if ((cmdParsed == NULL) || (cmdType == NULL)) { 55 return OS_INVALID; 56 } 57 58 len = strlen(cmdType); 59 LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) { 60 if ((len == strlen(curCmdItem->cmd->cmdKey)) && 61 (strncmp((CHAR *)(curCmdItem->cmd->cmdKey), cmdType, len) == 0)) { 62 minLen = (len < CMD_KEY_LEN) ? len : CMD_KEY_LEN; 63 (VOID)memcpy_s((CHAR *)(cmdParsed->cmdKeyword), CMD_KEY_LEN, cmdType, minLen); 64 cmdParsed->cmdType = curCmdItem->cmd->cmdType; 65 return LOS_OK; 66 } 67 } 68 69 return OS_INVALID; 70} 71 72CHAR *GetCmdName(const CHAR *cmdline, UINT32 len) 73{ 74 UINT32 loop; 75 const CHAR *tmpStr = NULL; 76 BOOL quotes = FALSE; 77 CHAR *cmdName = NULL; 78 if (cmdline == NULL) { 79 return NULL; 80 } 81 82 cmdName = (CHAR *)malloc(len + 1); 83 if (cmdName == NULL) { 84 PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); 85 return NULL; 86 } 87 88 /* Scan the 'cmdline' string for command */ 89 /* Notice: Command string must not have any special name */ 90 for (tmpStr = cmdline, loop = 0; (*tmpStr != '\0') && (loop < len); ) { 91 /* If reach a double quotes, switch the quotes matching status */ 92 if (*tmpStr == '\"') { 93 SWITCH_QUOTES_STATUS(quotes); 94 /* Ignore the double quote charactor itself */ 95 tmpStr++; 96 continue; 97 } 98 /* If detected a space which the quotes matching status is false */ 99 /* which said has detected the first space for separator, finish this scan operation */ 100 if ((*tmpStr == ' ') && (QUOTES_STATUS_CLOSE(quotes))) { 101 break; 102 } 103 cmdName[loop] = *tmpStr++; 104 loop++; 105 } 106 cmdName[loop] = '\0'; 107 108 return cmdName; 109} 110 111 112UINT32 PreHandleCmdline(const CHAR *input, CHAR **output, UINT32 *outputlen) 113{ 114 UINT32 shiftLen; 115 UINT32 ret; 116 const CHAR *cmdBuf = input; 117 UINT32 cmdBufLen = strlen(cmdBuf); 118 CHAR *shiftStr = (CHAR *)malloc(cmdBufLen + 1); 119 120 if (shiftStr == NULL) { 121 PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); 122 return SH_NOK; 123 } 124 (VOID)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1); 125 126 /* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */ 127 ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1); 128 shiftLen = strlen(shiftStr); 129 if ((ret != SH_OK) || (shiftLen == 0)) { 130 ret = SH_NOK; 131 goto END_FREE_SHIFTSTR; 132 } 133 *output = shiftStr; 134 *outputlen = shiftLen; 135 136 ret = SH_OK; 137 goto END; 138 139END_FREE_SHIFTSTR: 140 free(shiftStr); 141END: 142 return ret; 143} 144 145STATIC VOID ParseAndExecCmdline(CmdParsed *cmdParsed, const CHAR *cmdline, UINT32 len) 146{ 147 INT32 i; 148 UINT32 ret; 149 CHAR *cmdName = NULL; 150 151 cmdName = GetCmdName(cmdline, len); 152 if (cmdName == NULL) { 153 PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); 154 return; 155 } 156 157 ret = ShellMsgTypeGet(cmdParsed, cmdName); 158 if (ret != LOS_OK) { 159 PRINTK("%s:command not found\n", cmdName); 160 free(cmdName); 161 return; 162 } 163 164 ret = OsCmdParse((CHAR *)cmdline, cmdParsed); 165 if (ret != SH_OK) { 166 PRINTK("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__); 167 goto OUT; 168 } 169 170 (VOID)OsCmdExec(cmdParsed); 171 172OUT: 173 for (i = 0; i < cmdParsed->paramCnt; i++) { 174 if (cmdParsed->paramArray[i] != NULL) { 175 free(cmdParsed->paramArray[i]); 176 cmdParsed->paramArray[i] = NULL; 177 } 178 } 179 free(cmdName); 180} 181 182LITE_OS_SEC_TEXT_MINOR VOID ExecCmdline(const CHAR *cmdline) 183{ 184 UINT32 ret; 185 CHAR *output = NULL; 186 UINT32 outputlen; 187 CmdParsed cmdParsed; 188 189 if (cmdline == NULL) { 190 return; 191 } 192 193 (VOID)OsShellInit(); 194 195 /* strip out unnecessary characters */ 196 ret = PreHandleCmdline(cmdline, &output, &outputlen); 197 if (ret == SH_NOK) { 198 return; 199 } 200 201 (VOID)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed)); 202 ParseAndExecCmdline(&cmdParsed, output, outputlen); 203 free(output); 204} 205 206#if (LOSCFG_USE_SHELL == 1) 207VOID ShellTaskEntry(VOID) 208{ 209 CHAR buf[SHELL_CMD_MAX_SIZE] = {0}; 210 CHAR *ptr = buf; 211 PRINTK("OHOS # "); 212 while (1) { 213 (VOID)LOS_EventRead(&g_shellInputEvent, 0x1, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); 214 while ((*ptr = (UINT8)UartGetc()) != 0 && *ptr != 13) { 215 if (*ptr == '\x03') { /* ctrl + c */ 216 PRINTK("^C\n\rOHOS # "); 217 ptr = buf; 218 break; 219 } 220 if (*ptr == '\b' && ptr != buf) { /* support backspace */ 221 PRINTK("\b \b"); 222 ptr--; 223 break; 224 } 225 if (!VISIABLE_CHAR(*ptr)) { 226 break; 227 } 228 PRINTK("%c", *ptr); 229 if ((ptr - buf) == (sizeof(buf) - 1)) { 230 break; 231 } 232 ptr++; 233 } 234 if (ptr != buf) { 235 if (*ptr == 13 || ((ptr - buf) == (sizeof(buf) - 1))) { 236 *ptr = '\0'; 237 ptr = buf; 238 PRINTK("\n\r"); 239 ExecCmdline(buf); 240 PRINTK("OHOS # "); 241 } 242 } else if (*ptr == 13) { 243 PRINTK("\n\rOHOS # "); 244 } 245 } 246} 247 248LITE_OS_SEC_TEXT_MINOR UINT32 LosShellInit(VOID) 249{ 250 UINT32 ret; 251 UINT32 taskID1; 252 TSK_INIT_PARAM_S task1 = { 0 }; 253 254 ret = LOS_EventInit(&g_shellInputEvent); 255 if (ret != LOS_OK) { 256 PRINTK("Init shellInputEvent failed! ERROR: 0x%x\n", ret); 257 return ret; 258 } 259 260 task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ShellTaskEntry; 261 task1.uwStackSize = LOSCFG_SHELL_STACK_SIZE; 262 task1.pcName = "ShellTaskEntry"; 263 task1.usTaskPrio = LOSCFG_SHELL_PRIO; 264 ret = LOS_TaskCreate(&taskID1, &task1); 265 if (ret != LOS_OK) { 266 PRINTK("Create Shell Task failed! ERROR: 0x%x\n", ret); 267 return ret; 268 } 269 270 return ret; 271} 272#endif 273