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
52 STATIC CmdModInfo cmdInfo;
53 ShellCB *g_shellCB = NULL;
54 CmdItem 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
OsCmdInfoGet(VOID)91 CmdModInfo *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 */
OsCmdKeyShift(const CHAR * cmdKey,CHAR * cmdOut,UINT32 size)105 LITE_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
OsCmdKeyCheck(const CHAR * cmdKey)172 LITE_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
OsCmdAscendingInsert(CmdItemNode * cmd)211 LITE_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
OsShellKeyInit(ShellCB * shellCB)241 LITE_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
OsShellKeyDeInit(CmdKeyLink * cmdKeyLink)272 LITE_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
OsShellSysCmdRegister(VOID)289 LITE_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
OsCmdExec(CmdParsed * cmdParsed)311 LITE_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
OsGetShellCb(VOID)348 ShellCB *OsGetShellCb(VOID)
349 {
350 return g_shellCB;
351 }
352
OsShellGetWorkingDirtectory(VOID)353 CHAR *OsShellGetWorkingDirtectory(VOID)
354 {
355 return OsGetShellCb()->shellWorkingDirectory;
356 }
357
OsShellCBInit(VOID)358 VOID 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
381 ERR_OUT1:
382 (VOID)free(shellCB);
383 return;
384 }
385
OsCmdInit(VOID)386 LITE_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
OsCmdItemCreate(CmdType cmdType,const CHAR * cmdKey,UINT32 paraNum,CmdCallBackFunc cmdProc)402 STATIC 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 */
osCmdReg(CmdType cmdType,const CHAR * cmdKey,UINT32 paraNum,CmdCallBackFunc cmdProc)434 LITE_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