1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 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 "shcmd.h" 33#include "show.h" 34#include "shmsg.h" 35#include "stdlib.h" 36#include "unistd.h" 37#include "dirent.h" 38#include "securec.h" 39#include "los_mux.h" 40#include "los_memory.h" 41 42#if (LOSCFG_DEBUG_TOOLS == 1) 43#include "los_debugtools.h" 44#endif 45 46#if (LOSCFG_KERNEL_TRACE == 1) 47#include "los_trace_pri.h" 48#endif 49 50#define SHELL_INIT_MAGIC_FLAG 0xABABABAB 51 52STATIC CmdModInfo cmdInfo; 53ShellCB *g_shellCB = NULL; 54CmdItem g_shellcmdAll[] = { 55 {CMD_TYPE_STD, "date", XARGS, (CmdCallBackFunc)OsShellCmdDate}, 56 {CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask}, 57 {CMD_TYPE_EX, "free", XARGS, (CmdCallBackFunc)OsShellCmdFree}, 58#if (LOSCFG_MEM_WATERLINE == 1) 59 {CMD_TYPE_EX, "memusage", XARGS, (CmdCallBackFunc)OsShellCmdWaterLine}, 60#endif 61#ifdef LWIP_SHELLCMD_ENABLE 62 {CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig}, 63 {CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)OsShellPing}, 64#endif 65#if (LOSCFG_FS_VFS == 1) 66 {CMD_TYPE_EX, "touch", XARGS, (CmdCallBackFunc)OsShellCmdTouch}, 67 {CMD_TYPE_EX, "ls", XARGS, (CmdCallBackFunc)OsShellCmdLs}, 68 {CMD_TYPE_EX, "pwd", XARGS, (CmdCallBackFunc)OsShellCmdPwd}, 69 {CMD_TYPE_EX, "cd", XARGS, (CmdCallBackFunc)OsShellCmdCd}, 70 {CMD_TYPE_EX, "cat", XARGS, (CmdCallBackFunc)OsShellCmdCat}, 71 {CMD_TYPE_EX, "rm", XARGS, (CmdCallBackFunc)OsShellCmdRm}, 72 {CMD_TYPE_EX, "rmdir", XARGS, (CmdCallBackFunc)OsShellCmdRmdir}, 73 {CMD_TYPE_EX, "mkdir", XARGS, (CmdCallBackFunc)OsShellCmdMkdir}, 74 {CMD_TYPE_EX, "cp", XARGS, (CmdCallBackFunc)OsShellCmdCp}, 75#endif 76#if (LOSCFG_DEBUG_TOOLS == 1) 77 {CMD_TYPE_EX, "stack", 1, (CmdCallBackFunc)OsShellCmdStackDump}, 78 {CMD_TYPE_EX, "hwi", 1, (CmdCallBackFunc)OsShellCmdHwiDump}, 79 {CMD_TYPE_EX, "st", 1, (CmdCallBackFunc)OsShellCmdSchedTrace}, 80#endif 81 {CMD_TYPE_EX, "help", 0, (CmdCallBackFunc)OsShellCmdHelp}, 82#if (LOSCFG_KERNEL_TRACE == 1) 83 {CMD_TYPE_EX, "trace_start", 0, (CmdCallBackFunc)LOS_TraceStart}, 84 {CMD_TYPE_EX, "trace_stop", 0, (CmdCallBackFunc)LOS_TraceStop}, 85 {CMD_TYPE_EX, "trace_mask", 1, (CmdCallBackFunc)OsShellCmdTraceSetMask}, 86 {CMD_TYPE_EX, "trace_reset", 0, (CmdCallBackFunc)LOS_TraceReset}, 87 {CMD_TYPE_EX, "trace_dump", 1, (CmdCallBackFunc)OsShellCmdTraceDump}, 88#endif 89}; 90 91CmdModInfo *OsCmdInfoGet(VOID) 92{ 93 return &cmdInfo; 94} 95 96/* 97 * Description: Pass in the string and clear useless space ,which include: 98 * 1) The overmatch space which is not be marked by Quote's area 99 * Squeeze the overmatch space into one space 100 * 2) Clear all space before first valid character 101 * Input: cmdKey : Pass in the buff string, which is ready to be operated 102 * cmdOut : Pass out the buffer string ,which has already been operated 103 * size : cmdKey length 104 */ 105LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdKeyShift(const CHAR *cmdKey, CHAR *cmdOut, UINT32 size) 106{ 107 CHAR *output = NULL; 108 CHAR *outputBak = NULL; 109 UINT32 len; 110 INT32 ret; 111 BOOL quotes = FALSE; 112 113 if ((cmdKey == NULL) || (cmdOut == NULL)) { 114 return (UINT32)OS_ERROR; 115 } 116 117 len = strlen(cmdKey); 118 if (len >= size) { 119 return (UINT32)OS_ERROR; 120 } 121 output = (CHAR*)LOS_MemAlloc(m_aucSysMem0, len + 1); 122 if (output == NULL) { 123 PRINTK("malloc failure in %s[%d]", __FUNCTION__, __LINE__); 124 return (UINT32)OS_ERROR; 125 } 126 (VOID)memset_s(output, len + 1, 0, len + 1); 127 /* Backup the 'output' start address */ 128 outputBak = output; 129 /* Scan each charactor in 'cmdKey',and squeeze the overmuch space and ignore invalid charactor */ 130 for (; *cmdKey != '\0'; cmdKey++) { 131 /* Detected a Double Quotes, switch the matching status */ 132 if (*(cmdKey) == '\"') { 133 SWITCH_QUOTES_STATUS(quotes); 134 } 135 /* Ignore the current charactor in following situation */ 136 /* 1) Quotes matching status is FALSE (which said that the space is not been marked by double quotes) */ 137 /* 2) Current charactor is a space */ 138 /* 3) Next charactor is a space too, or the string is been seeked to the end already(\0) */ 139 /* 4) Invalid charactor, such as single quotes */ 140 if ((*cmdKey == ' ') && ((*(cmdKey + 1) == ' ') || (*(cmdKey + 1) == '\0')) && QUOTES_STATUS_CLOSE(quotes)) { 141 continue; 142 } 143 if (*cmdKey == '\'') { 144 continue; 145 } 146 *output = *cmdKey; 147 output++; 148 } 149 *output = '\0'; 150 /* Restore the 'output' start address */ 151 output = outputBak; 152 len = strlen(output); 153 /* Clear the space which is located at the first charactor in buffer */ 154 if (*outputBak == ' ') { 155 output++; 156 len--; 157 } 158 /* Copy out the buffer which is been operated already */ 159 ret = strncpy_s(cmdOut, size, output, len); 160 if (ret != EOK) { 161 PRINT_ERR("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret); 162 (VOID)LOS_MemFree(m_aucSysMem0, output); 163 return OS_ERROR; 164 } 165 cmdOut[len] = '\0'; 166 167 (VOID)LOS_MemFree(m_aucSysMem0, output); 168 169 return LOS_OK; 170} 171 172LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey) 173{ 174 const CHAR *temp = cmdKey; 175 enum Stat { 176 STAT_NONE, 177 STAT_DIGIT, 178 STAT_OTHER 179 } state = STAT_NONE; 180 181 if (strlen(cmdKey) >= CMD_KEY_LEN) { 182 return FALSE; 183 } 184 185 while (*temp != '\0') { 186 if (!((*temp <= '9') && (*temp >= '0')) && 187 !((*temp <= 'z') && (*temp >= 'a')) && 188 !((*temp <= 'Z') && (*temp >= 'A')) && 189 (*temp != '_') && (*temp != '-')) { 190 return FALSE; 191 } 192 193 if ((*temp >= '0') && (*temp <= '9')) { 194 if (state == STAT_NONE) { 195 state = STAT_DIGIT; 196 } 197 } else { 198 state = STAT_OTHER; 199 } 200 201 temp++; 202 } 203 204 if (state == STAT_DIGIT) { 205 return FALSE; 206 } 207 208 return TRUE; 209} 210 211LITE_OS_SEC_TEXT_MINOR VOID OsCmdAscendingInsert(CmdItemNode *cmd) 212{ 213 CmdItemNode *cmdItem = NULL; 214 CmdItemNode *cmdNext = NULL; 215 216 if (cmd == NULL) { 217 return; 218 } 219 220 for (cmdItem = LOS_DL_LIST_ENTRY((&cmdInfo.cmdList.list)->pstPrev, CmdItemNode, list); 221 &cmdItem->list != &(cmdInfo.cmdList.list);) { 222 cmdNext = LOS_DL_LIST_ENTRY(cmdItem->list.pstPrev, CmdItemNode, list); 223 if (&cmdNext->list != &(cmdInfo.cmdList.list)) { 224 if ((strncmp(cmdItem->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) >= 0) && 225 (strncmp(cmdNext->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) < 0)) { 226 LOS_ListTailInsert(&(cmdItem->list), &(cmd->list)); 227 return; 228 } 229 cmdItem = cmdNext; 230 } else { 231 if (strncmp(cmd->cmd->cmdKey, cmdItem->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) > 0) { 232 cmdItem = cmdNext; 233 } 234 break; 235 } 236 } 237 238 LOS_ListTailInsert(&(cmdItem->list), &(cmd->list)); 239} 240 241LITE_OS_SEC_TEXT_MINOR UINT32 OsShellKeyInit(ShellCB *shellCB) 242{ 243 CmdKeyLink *cmdKeyLink = NULL; 244 CmdKeyLink *cmdHistoryLink = NULL; 245 246 if (shellCB == NULL) { 247 return OS_ERROR; 248 } 249 cmdKeyLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink)); 250 if (cmdKeyLink == NULL) { 251 PRINT_ERR("Shell CmdKeyLink memory alloc error!\n"); 252 return OS_ERROR; 253 } 254 cmdHistoryLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink)); 255 if (cmdHistoryLink == NULL) { 256 (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink); 257 PRINT_ERR("Shell CmdHistoryLink memory alloc error!\n"); 258 return OS_ERROR; 259 } 260 261 cmdKeyLink->count = 0; 262 LOS_ListInit(&(cmdKeyLink->list)); 263 shellCB->cmdKeyLink = (VOID *)cmdKeyLink; 264 265 cmdHistoryLink->count = 0; 266 LOS_ListInit(&(cmdHistoryLink->list)); 267 shellCB->cmdHistoryKeyLink = (VOID *)cmdHistoryLink; 268 shellCB->cmdMaskKeyLink = (VOID *)cmdHistoryLink; 269 return LOS_OK; 270} 271 272LITE_OS_SEC_TEXT_MINOR VOID OsShellKeyDeInit(CmdKeyLink *cmdKeyLink) 273{ 274 CmdKeyLink *cmdtmp = NULL; 275 if (cmdKeyLink == NULL) { 276 return; 277 } 278 279 while (!LOS_ListEmpty(&(cmdKeyLink->list))) { 280 cmdtmp = LOS_DL_LIST_ENTRY(cmdKeyLink->list.pstNext, CmdKeyLink, list); 281 LOS_ListDelete(&cmdtmp->list); 282 (VOID)LOS_MemFree(m_aucSysMem0, cmdtmp); 283 } 284 285 cmdKeyLink->count = 0; 286 (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink); 287} 288 289LITE_OS_SEC_TEXT_MINOR UINT32 OsShellSysCmdRegister(VOID) 290{ 291 UINT32 i; 292 UINT8 *cmdItemGroup = NULL; 293 UINT32 index = sizeof(g_shellcmdAll) / sizeof(CmdItem); 294 CmdItemNode *cmdItem = NULL; 295 296 cmdItemGroup = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, index * sizeof(CmdItemNode)); 297 if (cmdItemGroup == NULL) { 298 PRINT_ERR("[%s]System memory allocation failure!\n", __FUNCTION__); 299 return (UINT32)OS_ERROR; 300 } 301 302 for (i = 0; i < index; ++i) { 303 cmdItem = (CmdItemNode *)(cmdItemGroup + i * sizeof(CmdItemNode)); 304 cmdItem->cmd = &g_shellcmdAll[i]; 305 OsCmdAscendingInsert(cmdItem); 306 } 307 cmdInfo.listNum += index; 308 return LOS_OK; 309} 310 311LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed) 312{ 313 UINT32 ret; 314 CmdCallBackFunc cmdHook = NULL; 315 CmdItemNode *curCmdItem = NULL; 316 UINT32 i; 317 const CHAR *cmdKey = NULL; 318 319 if (cmdParsed == NULL) { 320 return (UINT32)OS_ERROR; 321 } 322 323 LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo.cmdList.list), CmdItemNode, list) { 324 cmdKey = curCmdItem->cmd->cmdKey; 325 if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) && 326 (strlen(cmdKey) == strlen(cmdParsed->cmdKeyword)) && 327 (strncmp(cmdKey, (CHAR *)(cmdParsed->cmdKeyword), strlen(cmdKey)) == 0)) { 328 cmdHook = curCmdItem->cmd->cmdHook; 329 break; 330 } 331 } 332 333 ret = OS_ERROR; 334 if (cmdHook != NULL) { 335 ret = (cmdHook)(cmdParsed->paramCnt, (const CHAR **)cmdParsed->paramArray); 336 } 337 338 for (i = 0; i < cmdParsed->paramCnt; i++) { 339 if (cmdParsed->paramArray[i] != NULL) { 340 (VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]); 341 cmdParsed->paramArray[i] = NULL; 342 } 343 } 344 345 return (UINT32)ret; 346} 347 348ShellCB *OsGetShellCb(VOID) 349{ 350 return g_shellCB; 351} 352 353CHAR *OsShellGetWorkingDirtectory(VOID) 354{ 355 return OsGetShellCb()->shellWorkingDirectory; 356} 357 358VOID OsShellCBInit(VOID) 359{ 360 INT32 ret; 361 ShellCB *shellCB = NULL; 362 363 shellCB = (ShellCB *)malloc(sizeof(ShellCB)); 364 if (shellCB == NULL) { 365 goto ERR_OUT1; 366 } 367 ret = memset_s(shellCB, sizeof(ShellCB), 0, sizeof(ShellCB)); 368 if (ret != SH_OK) { 369 goto ERR_OUT1; 370 } 371 372 ret = (INT32)OsShellKeyInit(shellCB); 373 if (ret != SH_OK) { 374 goto ERR_OUT1; 375 } 376 (VOID)strncpy_s(shellCB->shellWorkingDirectory, PATH_MAX, "/", 2); /* 2:space for "/" */ 377 378 g_shellCB = shellCB; 379 return; 380 381ERR_OUT1: 382 (VOID)free(shellCB); 383 return; 384} 385 386LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdInit(VOID) 387{ 388 UINT32 ret; 389 LOS_ListInit(&(cmdInfo.cmdList.list)); 390 cmdInfo.listNum = 0; 391 cmdInfo.initMagicFlag = SHELL_INIT_MAGIC_FLAG; 392 ret = LOS_MuxCreate(&cmdInfo.muxLock); 393 if (ret != LOS_OK) { 394 PRINT_ERR("Create mutex for shell cmd info failed\n"); 395 return OS_ERROR; 396 } 397 OsShellCBInit(); 398 399 return LOS_OK; 400} 401 402STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) 403{ 404 CmdItem *cmdItem = NULL; 405 CmdItemNode *cmdItemNode = NULL; 406 407 cmdItem = (CmdItem *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItem)); 408 if (cmdItem == NULL) { 409 return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR; 410 } 411 (VOID)memset_s(cmdItem, sizeof(CmdItem), '\0', sizeof(CmdItem)); 412 413 cmdItemNode = (CmdItemNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItemNode)); 414 if (cmdItemNode == NULL) { 415 (VOID)LOS_MemFree(m_aucSysMem0, cmdItem); 416 return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR; 417 } 418 (VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode)); 419 cmdItemNode->cmd = cmdItem; 420 cmdItemNode->cmd->cmdHook = cmdProc; 421 cmdItemNode->cmd->paraNum = paraNum; 422 cmdItemNode->cmd->cmdType = cmdType; 423 cmdItemNode->cmd->cmdKey = cmdKey; 424 425 (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); 426 OsCmdAscendingInsert(cmdItemNode); 427 cmdInfo.listNum++; 428 (VOID)LOS_MuxPost(cmdInfo.muxLock); 429 430 return LOS_OK; 431} 432 433/* open API */ 434LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) 435{ 436 CmdItemNode *cmdItemNode = NULL; 437 438 (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); 439 if (cmdInfo.initMagicFlag != SHELL_INIT_MAGIC_FLAG) { 440 (VOID)LOS_MuxPost(cmdInfo.muxLock); 441 PRINT_ERR("[%s] shell is not yet initialized!\n", __FUNCTION__); 442 return OS_ERRNO_SHELL_NOT_INIT; 443 } 444 (VOID)LOS_MuxPost(cmdInfo.muxLock); 445 446 if ((cmdProc == NULL) || (cmdKey == NULL) || 447 (cmdType >= CMD_TYPE_BUTT) || (strlen(cmdKey) >= CMD_KEY_LEN) || !strlen(cmdKey)) { 448 return OS_ERRNO_SHELL_CMDREG_PARA_ERROR; 449 } 450 451 if (paraNum > CMD_MAX_PARAS) { 452 if (paraNum != XARGS) { 453 return OS_ERRNO_SHELL_CMDREG_PARA_ERROR; 454 } 455 } 456 457 if (OsCmdKeyCheck(cmdKey) != TRUE) { 458 return OS_ERRNO_SHELL_CMDREG_CMD_ERROR; 459 } 460 461 (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); 462 LOS_DL_LIST_FOR_EACH_ENTRY(cmdItemNode, &(cmdInfo.cmdList.list), CmdItemNode, list) { 463 if ((cmdType == cmdItemNode->cmd->cmdType) && 464 ((strlen(cmdKey) == strlen(cmdItemNode->cmd->cmdKey)) && 465 (strncmp((CHAR *)(cmdItemNode->cmd->cmdKey), cmdKey, strlen(cmdKey)) == 0))) { 466 (VOID)LOS_MuxPost(cmdInfo.muxLock); 467 return OS_ERRNO_SHELL_CMDREG_CMD_EXIST; 468 } 469 } 470 (VOID)LOS_MuxPost(cmdInfo.muxLock); 471 472 return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc); 473} 474 475