• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "shcmd.h"
33 #include "shell_pri.h"
34 #include "show.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 #include "los_typedef.h"
42 
43 
44 #define SHELL_INIT_MAGIC_FLAG 0xABABABAB
45 #define CTRL_C 0x03 /* 0x03: ctrl+c ASCII */
46 
47 STATIC CmdModInfo g_cmdInfo;
48 
49 LOS_HAL_TABLE_BEGIN(g_shellcmd, shellcmd);
50 LOS_HAL_TABLE_END(g_shellcmdEnd, shellcmd);
51 
OsCmdInfoGet(VOID)52 CmdModInfo *OsCmdInfoGet(VOID)
53 {
54     return &g_cmdInfo;
55 }
56 
OsFreeCmdPara(CmdParsed * cmdParsed)57 STATIC VOID OsFreeCmdPara(CmdParsed *cmdParsed)
58 {
59     UINT32 i;
60     for (i = 0; i < cmdParsed->paramCnt; i++) {
61         if ((cmdParsed->paramArray[i]) != NULL) {
62             (VOID)LOS_MemFree(m_aucSysMem0, (cmdParsed->paramArray[i]));
63             cmdParsed->paramArray[i] = NULL;
64         }
65     }
66 }
67 
OsStrSeparateTabStrGet(CHAR ** tabStr,CmdParsed * parsed,UINT32 tabStrLen)68 STATIC INT32 OsStrSeparateTabStrGet(CHAR **tabStr, CmdParsed *parsed, UINT32 tabStrLen)
69 {
70     CHAR *shiftStr = NULL;
71     CHAR *tempStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, SHOW_MAX_LEN << 1);
72     if (tempStr == NULL) {
73         return (INT32)OS_ERROR;
74     }
75 
76     (VOID)memset_s(tempStr, SHOW_MAX_LEN << 1, 0, SHOW_MAX_LEN << 1);
77     shiftStr = tempStr + SHOW_MAX_LEN;
78 
79     if (strncpy_s(tempStr, SHOW_MAX_LEN - 1, *tabStr, tabStrLen)) {
80         (VOID)LOS_MemFree(m_aucSysMem0, tempStr);
81         return (INT32)OS_ERROR;
82     }
83 
84     parsed->cmdType = CMD_TYPE_STD;
85 
86     /* cut useless or repeat space */
87     if (OsCmdKeyShift(tempStr, shiftStr, SHOW_MAX_LEN - 1)) {
88         (VOID)LOS_MemFree(m_aucSysMem0, tempStr);
89         return (INT32)OS_ERROR;
90     }
91 
92     /* get exact position of string to complete */
93     /* situation different if end space lost or still exist */
94     if ((strlen(shiftStr) == 0) || (tempStr[strlen(tempStr) - 1] != shiftStr[strlen(shiftStr) - 1])) {
95         *tabStr = "";
96     } else {
97         if (OsCmdTokenSplit(shiftStr, ' ', parsed)) {
98             (VOID)LOS_MemFree(m_aucSysMem0, tempStr);
99             return (INT32)OS_ERROR;
100         }
101         *tabStr = parsed->paramArray[parsed->paramCnt - 1];
102     }
103 
104     (VOID)LOS_MemFree(m_aucSysMem0, tempStr);
105     return LOS_OK;
106 }
107 
OsStrSeparate(CHAR * tabStr,CHAR * strPath,CHAR * nameLooking,UINT32 tabStrLen)108 STATIC INT32 OsStrSeparate(CHAR *tabStr, CHAR *strPath, CHAR *nameLooking, UINT32 tabStrLen)
109 {
110     CHAR *strEnd = NULL;
111     CHAR *cutPos = NULL;
112     CmdParsed parsed = {0};
113     CHAR *shellWorkingDirectory = OsShellGetWorkingDirectory();
114     INT32 ret;
115 
116     ret = OsStrSeparateTabStrGet(&tabStr, &parsed, tabStrLen);
117     if (ret != LOS_OK) {
118         return ret;
119     }
120 
121     /* get fullpath str */
122     if (*tabStr != '/') {
123         if (strncpy_s(strPath, CMD_MAX_PATH, shellWorkingDirectory, CMD_MAX_PATH - 1)) {
124             OsFreeCmdPara(&parsed);
125             return (INT32)OS_ERROR;
126         }
127         if (strcmp(shellWorkingDirectory, "/")) {
128             if (strncat_s(strPath, CMD_MAX_PATH, "/", CMD_MAX_PATH - strlen(strPath) - 1)) {
129                 OsFreeCmdPara(&parsed);
130                 return (INT32)OS_ERROR;
131             }
132         }
133     }
134 
135     if (strncat_s(strPath, CMD_MAX_PATH, tabStr, CMD_MAX_PATH - strlen(strPath) - 1)) {
136         OsFreeCmdPara(&parsed);
137         return (INT32)OS_ERROR;
138     }
139 
140     /* split str by last '/' */
141     strEnd = strrchr(strPath, '/');
142     cutPos = strEnd;
143     if (strEnd != NULL) {
144         if (strncpy_s(nameLooking, CMD_MAX_PATH, strEnd + 1, CMD_MAX_PATH - 1)) { /* get cmp str */
145             OsFreeCmdPara(&parsed);
146             return (INT32)OS_ERROR;
147         }
148         *(cutPos + 1) = '\0';
149     }
150 
151     OsFreeCmdPara(&parsed);
152     return LOS_OK;
153 }
154 
OsShowPageInputControl(VOID)155 STATIC INT32 OsShowPageInputControl(VOID)
156 {
157     CHAR readChar;
158 
159     while (1) {
160         if (read(STDIN_FILENO, &readChar, 1) != 1) { /* get one CHAR from stdin */
161             PRINTK("\n");
162             return (INT32)OS_ERROR;
163         }
164         if ((readChar == 'q') || (readChar == 'Q') || (readChar == CTRL_C)) {
165             PRINTK("\n");
166             return 0;
167         } else if (readChar == '\r') {
168             PRINTK("\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b");
169             return 1;
170         }
171     }
172 }
173 
OsShowPageControl(UINT32 timesPrint,UINT32 lineCap,UINT32 count)174 STATIC INT32 OsShowPageControl(UINT32 timesPrint, UINT32 lineCap, UINT32 count)
175 {
176     if (NEED_NEW_LINE(timesPrint, lineCap)) {
177         PRINTK("\n");
178         if (SCREEN_IS_FULL(timesPrint, lineCap) && (timesPrint < count)) {
179             PRINTK("--More--");
180             return OsShowPageInputControl();
181         }
182     }
183     return 1;
184 }
185 
OsSurePrintAll(UINT32 count)186 STATIC INT32 OsSurePrintAll(UINT32 count)
187 {
188     CHAR readChar = 0;
189     PRINTK("\nDisplay all %u possibilities?(y/n)", count);
190     while (1) {
191         if (read(0, &readChar, 1) != 1) {
192             return (INT32)OS_ERROR;
193         }
194         if ((readChar == 'n') || (readChar == 'N') || (readChar == CTRL_C)) {
195             PRINTK("\n");
196             return 0;
197         } else if ((readChar == 'y') || (readChar == 'Y') || (readChar == '\r')) {
198             return 1;
199         }
200     }
201 }
202 
OsPrintMatchList(UINT32 count,const CHAR * strPath,const CHAR * nameLooking,UINT32 printLen)203 STATIC INT32 OsPrintMatchList(UINT32 count, const CHAR *strPath, const CHAR *nameLooking, UINT32 printLen)
204 {
205     UINT32 timesPrint = 0;
206     UINT32 lineCap;
207     INT32 ret;
208     DIR *openDir = NULL;
209     struct dirent *readDir = NULL;
210     CHAR formatChar[10] = {0}; /* 10:for formatChar length */
211 
212     printLen = (printLen > (DEFAULT_SCREEN_WIDTH - 2)) ? (DEFAULT_SCREEN_WIDTH - 2) : printLen; /* 2:revered 2 bytes */
213     lineCap = DEFAULT_SCREEN_WIDTH / (printLen + 2); /* 2:DEFAULT_SCREEN_WIDTH revered 2 bytes */
214     if (snprintf_s(formatChar, sizeof(formatChar) - 1, 7, "%%-%us  ", printLen) < 0) { /* 7:format-len */
215         return (INT32)OS_ERROR;
216     }
217 
218     if (count > (lineCap * DEFAULT_SCREEN_HEIGHT)) {
219         ret = OsSurePrintAll(count);
220         if (ret != 1) {
221             return ret;
222         }
223     }
224     openDir = opendir(strPath);
225     if (openDir == NULL) {
226         return (INT32)OS_ERROR;
227     }
228 
229     PRINTK("\n");
230     for (readDir = readdir(openDir); readDir != NULL; readDir = readdir(openDir)) {
231         if (strncmp(nameLooking, readDir->d_name, strlen(nameLooking)) != 0) {
232             continue;
233         }
234         PRINTK(formatChar, readDir->d_name);
235         timesPrint++;
236         ret = OsShowPageControl(timesPrint, lineCap, count);
237         if (ret != 1) {
238             if (closedir(openDir) < 0) {
239                 return (INT32)OS_ERROR;
240             }
241             return ret;
242         }
243     }
244 
245     PRINTK("\n");
246     if (closedir(openDir) < 0) {
247         return (INT32)OS_ERROR;
248     }
249 
250     return LOS_OK;
251 }
252 
strncmp_cut(const CHAR * s1,CHAR * s2,size_t n)253 STATIC VOID strncmp_cut(const CHAR *s1, CHAR *s2, size_t n)
254 {
255     if ((n == 0) || (s1 == NULL) || (s2 == NULL)) {
256         return;
257     }
258     do {
259         if (*s1 && *s2 && (*s1 == *s2)) {
260             s1++;
261             s2++;
262         } else {
263             break;
264         }
265     } while (--n != 0);
266     if (n > 0) {
267         /* NULL pad the remaining n-1 bytes */
268         while (n-- != 0)
269             *s2++ = 0;
270     }
271     return;
272 }
OsExecNameMatch(const CHAR * strPath,const CHAR * nameLooking,CHAR * strObj,UINT32 * maxLen)273 STATIC INT32 OsExecNameMatch(const CHAR *strPath, const CHAR *nameLooking, CHAR *strObj, UINT32 *maxLen)
274 {
275     INT32 count = 0;
276     DIR *openDir = NULL;
277     struct dirent *readDir = NULL;
278 
279     openDir = opendir(strPath);
280     if (openDir == NULL) {
281         return (INT32)OS_ERROR;
282     }
283 
284     for (readDir = readdir(openDir); readDir != NULL; readDir = readdir(openDir)) {
285         if (strncmp(nameLooking, readDir->d_name, strlen(nameLooking)) != 0) {
286             continue;
287         }
288         if (count == 0) {
289             if (strncpy_s(strObj, CMD_MAX_PATH, readDir->d_name, CMD_MAX_PATH - 1)) {
290                 (VOID)closedir(openDir);
291                 return (INT32)OS_ERROR;
292             }
293             *maxLen = strlen(readDir->d_name);
294         } else {
295             /* strncmp&cut the same strings of name matched */
296             strncmp_cut(readDir->d_name, strObj, strlen(strObj));
297             if (strlen(readDir->d_name) > *maxLen) {
298                 *maxLen = strlen(readDir->d_name);
299             }
300         }
301         count++;
302     }
303 
304     if (closedir(openDir) < 0) {
305         return (INT32)OS_ERROR;
306     }
307 
308     return count;
309 }
310 
OsCompleteStr(const CHAR * result,const CHAR * target,CHAR * cmdKey,UINT32 * len)311 STATIC VOID OsCompleteStr(const CHAR *result, const CHAR *target, CHAR *cmdKey, UINT32 *len)
312 {
313     UINT32 size = strlen(result) - strlen(target);
314     CHAR *des = cmdKey + *len;
315     CHAR *src = (CHAR *)result + strlen(target);
316 
317     while (size-- > 0) {
318         PRINTK("%c", *src);
319         if (*len == (SHOW_MAX_LEN - 1)) {
320             *des = '\0';
321             break;
322         }
323         *des++ = *src++;
324         (*len)++;
325     }
326 }
327 
OsTabMatchCmd(CHAR * cmdKey,UINT32 * len)328 STATIC INT32 OsTabMatchCmd(CHAR *cmdKey, UINT32 *len)
329 {
330     INT32 count = 0;
331     INT32 ret;
332     CmdItemNode *cmdItemGuard = NULL;
333     CmdItemNode *curCmdItem = NULL;
334     const CHAR *cmdMajor = (const CHAR *)cmdKey;
335 
336     while (*cmdMajor == 0x20) { /* cut left space */
337         cmdMajor++;
338     }
339 
340     if (LOS_ListEmpty(&(g_cmdInfo.cmdList.list))) {
341         return (INT32)OS_ERROR;
342     }
343 
344     LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(g_cmdInfo.cmdList.list), CmdItemNode, list) {
345         if ((curCmdItem == NULL) || (curCmdItem->cmd == NULL)) {
346             return -1;
347         }
348 
349         if (strncmp(cmdMajor, curCmdItem->cmd->cmdKey, strlen(cmdMajor)) > 0) {
350             continue;
351         }
352 
353         if (strncmp(cmdMajor, curCmdItem->cmd->cmdKey, strlen(cmdMajor)) != 0) {
354             break;
355         }
356 
357         if (count == 0) {
358             cmdItemGuard = curCmdItem;
359         }
360         ++count;
361     }
362 
363     if (cmdItemGuard == NULL) {
364         return 0;
365     }
366 
367     if (count == 1) {
368         OsCompleteStr(cmdItemGuard->cmd->cmdKey, cmdMajor, cmdKey, len);
369     }
370 
371     ret = count;
372     if (count > 1) {
373         PRINTK("\n");
374         while (count--) {
375             PRINTK("%s  ", cmdItemGuard->cmd->cmdKey);
376             cmdItemGuard = LOS_DL_LIST_ENTRY(cmdItemGuard->list.pstNext, CmdItemNode, list);
377         }
378         PRINTK("\n");
379     }
380 
381     return ret;
382 }
383 
OsTabMatchFile(CHAR * cmdKey,UINT32 * len)384 STATIC INT32 OsTabMatchFile(CHAR *cmdKey, UINT32 *len)
385 {
386     UINT32 maxLen = 0;
387     INT32 count;
388     CHAR *strOutput = NULL;
389     CHAR *strCmp = NULL;
390     CHAR *dirOpen = (CHAR *)LOS_MemAlloc(m_aucSysMem0, CMD_MAX_PATH * 3); /* 3:dirOpen\strOutput\strCmp */
391     if (dirOpen == NULL) {
392         return (INT32)OS_ERROR;
393     }
394 
395     (VOID)memset_s(dirOpen, CMD_MAX_PATH * 3, 0, CMD_MAX_PATH * 3); /* 3:dirOpen\strOutput\strCmp */
396     strOutput = dirOpen + CMD_MAX_PATH;
397     strCmp = strOutput + CMD_MAX_PATH;
398 
399     if (OsStrSeparate(cmdKey, dirOpen, strCmp, *len)) {
400         (VOID)LOS_MemFree(m_aucSysMem0, dirOpen);
401         return (INT32)OS_ERROR;
402     }
403 
404     count = OsExecNameMatch(dirOpen, strCmp, strOutput, &maxLen);
405     /* one or more matched */
406     if (count >= 1) {
407         OsCompleteStr(strOutput, strCmp, cmdKey, len);
408 
409         if (count == 1) {
410             (VOID)LOS_MemFree(m_aucSysMem0, dirOpen);
411             return 1;
412         }
413         if (OsPrintMatchList((UINT32)count, dirOpen, strCmp, maxLen) == -1) {
414             (VOID)LOS_MemFree(m_aucSysMem0, dirOpen);
415             return (INT32)OS_ERROR;
416         }
417     }
418 
419     (VOID)LOS_MemFree(m_aucSysMem0, dirOpen);
420     return count;
421 }
422 
423 /*
424  * Description: Pass in the string and clear useless space, which include:
425  *                1) The overmatch space which is not be marked by Quote's area
426  *                   Squeeze the overmatch space into one space
427  *                2) Clear all space before first valid character
428  * Input:       cmdKey : Pass in the buff string, which is ready to be operated
429  *              cmdOut : Pass out the buffer string ,which has already been operated
430  *              size : cmdKey length
431  */
OsCmdKeyShift(const CHAR * cmdKey,CHAR * cmdOut,UINT32 size)432 LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdKeyShift(const CHAR *cmdKey, CHAR *cmdOut, UINT32 size)
433 {
434     CHAR *output = NULL;
435     CHAR *outputBak = NULL;
436     UINT32 len;
437     INT32 ret;
438     BOOL quotes = FALSE;
439 
440     if ((cmdKey == NULL) || (cmdOut == NULL)) {
441         return (UINT32)OS_ERROR;
442     }
443 
444     len = strlen(cmdKey);
445     if (len >= size) {
446         return (UINT32)OS_ERROR;
447     }
448     output = (CHAR*)LOS_MemAlloc(m_aucSysMem0, len + 1);
449     if (output == NULL) {
450         PRINTK("malloc failure in %s[%d]", __FUNCTION__, __LINE__);
451         return (UINT32)OS_ERROR;
452     }
453     /* Backup the 'output' start address */
454     outputBak = output;
455     /* Scan each character in 'cmdKey',and squeeze the overmuch space and ignore invalid character */
456     for (; *cmdKey != '\0'; cmdKey++) {
457         /* Detected a Double Quotes, switch the matching status */
458         if (*(cmdKey) == '\"') {
459             SWITCH_QUOTES_STATUS(quotes);
460         }
461         /* Ignore the current character in following situation */
462         /* 1) Quotes matching status is FALSE (which said that the space is not been marked by double quotes) */
463         /* 2) Current character is a space */
464         /* 3) Next character is a space too, or the string is been seeked to the end already(\0) */
465         /* 4) Invalid character, such as single quotes */
466         if ((*cmdKey == ' ') && ((*(cmdKey + 1) == ' ') || (*(cmdKey + 1) == '\0')) && QUOTES_STATUS_CLOSE(quotes)) {
467             continue;
468         }
469         if (*cmdKey == '\'') {
470             continue;
471         }
472         *output = *cmdKey;
473         output++;
474     }
475     *output = '\0';
476     /* Restore the 'output' start address */
477     output = outputBak;
478     len = strlen(output);
479     /* Clear the space which is located at the first character in buffer */
480     if (*outputBak == ' ') {
481         output++;
482         len--;
483     }
484     /* Copy out the buffer which is been operated already */
485     ret = strncpy_s(cmdOut, size, output, len);
486     if (ret != EOK) {
487         PRINT_ERR("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret);
488         (VOID)LOS_MemFree(m_aucSysMem0, output);
489         return OS_ERROR;
490     }
491     cmdOut[len] = '\0';
492 
493     (VOID)LOS_MemFree(m_aucSysMem0, output);
494 
495     return LOS_OK;
496 }
497 
OsCmdKeyCheck(const CHAR * cmdKey)498 LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey)
499 {
500     const CHAR *temp = cmdKey;
501     enum Stat {
502         STAT_NONE,
503         STAT_DIGIT,
504         STAT_OTHER
505     } state = STAT_NONE;
506 
507     if (strlen(cmdKey) >= CMD_KEY_LEN) {
508         return FALSE;
509     }
510 
511     while (*temp != '\0') {
512         if (!((*temp <= '9') && (*temp >= '0')) &&
513             !((*temp <= 'z') && (*temp >= 'a')) &&
514             !((*temp <= 'Z') && (*temp >= 'A')) &&
515             (*temp != '_') && (*temp != '-')) {
516             return FALSE;
517         }
518 
519         if ((*temp >= '0') && (*temp <= '9')) {
520             if (state == STAT_NONE) {
521                 state = STAT_DIGIT;
522             }
523         } else {
524             state = STAT_OTHER;
525         }
526 
527         temp++;
528     }
529 
530     if (state == STAT_DIGIT) {
531         return FALSE;
532     }
533 
534     return TRUE;
535 }
536 
OsTabCompletion(CHAR * cmdKey,UINT32 * len)537 LITE_OS_SEC_TEXT_MINOR INT32 OsTabCompletion(CHAR *cmdKey, UINT32 *len)
538 {
539     INT32 count = 0;
540     CHAR *space = NULL;
541     CHAR *cmdMainStr = cmdKey;
542 
543     if ((cmdKey == NULL) || (len == NULL)) {
544         return (INT32)OS_ERROR;
545     }
546 
547     /* cut left space */
548     while (*cmdMainStr == 0x20) {
549         cmdMainStr++;
550     }
551 
552     /* try to find space in remain */
553     space = strrchr(cmdMainStr, 0x20);
554     if ((space == NULL) && (*cmdMainStr != '\0')) {
555         count = OsTabMatchCmd(cmdKey, len);
556     }
557 
558     if (count == 0) {
559         count = OsTabMatchFile(cmdKey, len);
560     }
561 
562     return count;
563 }
564 
OsCmdAscendingInsert(CmdItemNode * cmd)565 LITE_OS_SEC_TEXT_MINOR VOID OsCmdAscendingInsert(CmdItemNode *cmd)
566 {
567     CmdItemNode *cmdItem = NULL;
568     CmdItemNode *cmdNext = NULL;
569 
570     if (cmd == NULL) {
571         return;
572     }
573 
574     for (cmdItem = LOS_DL_LIST_ENTRY((&g_cmdInfo.cmdList.list)->pstPrev, CmdItemNode, list);
575          &cmdItem->list != &(g_cmdInfo.cmdList.list);) {
576         cmdNext = LOS_DL_LIST_ENTRY(cmdItem->list.pstPrev, CmdItemNode, list);
577         if (&cmdNext->list != &(g_cmdInfo.cmdList.list)) {
578             if ((strncmp(cmdItem->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) >= 0) &&
579                 (strncmp(cmdNext->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) < 0)) {
580                 LOS_ListTailInsert(&(cmdItem->list), &(cmd->list));
581                 return;
582             }
583             cmdItem = cmdNext;
584         } else {
585             if (strncmp(cmd->cmd->cmdKey, cmdItem->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) > 0) {
586                 cmdItem = cmdNext;
587             }
588             break;
589         }
590     }
591 
592     LOS_ListTailInsert(&(cmdItem->list), &(cmd->list));
593 }
594 
OsShellKeyInit(ShellCB * shellCB)595 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellKeyInit(ShellCB *shellCB)
596 {
597     CmdKeyLink *cmdKeyLink = NULL;
598     CmdKeyLink *cmdHistoryLink = NULL;
599 
600     if (shellCB == NULL) {
601         return OS_ERROR;
602     }
603     cmdKeyLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink));
604     if (cmdKeyLink == NULL) {
605         PRINT_ERR("Shell CmdKeyLink memory alloc error!\n");
606         return OS_ERROR;
607     }
608     cmdHistoryLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink));
609     if (cmdHistoryLink == NULL) {
610         (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink);
611         PRINT_ERR("Shell CmdHistoryLink memory alloc error!\n");
612         return OS_ERROR;
613     }
614 
615     cmdKeyLink->count = 0;
616     LOS_ListInit(&(cmdKeyLink->list));
617     shellCB->cmdKeyLink = (VOID *)cmdKeyLink;
618 
619     cmdHistoryLink->count = 0;
620     LOS_ListInit(&(cmdHistoryLink->list));
621     shellCB->cmdHistoryKeyLink = (VOID *)cmdHistoryLink;
622     shellCB->cmdMaskKeyLink = (VOID *)cmdHistoryLink;
623     return LOS_OK;
624 }
625 
OsShellKeyDeInit(CmdKeyLink * cmdKeyLink)626 LITE_OS_SEC_TEXT_MINOR VOID OsShellKeyDeInit(CmdKeyLink *cmdKeyLink)
627 {
628     CmdKeyLink *cmdtmp = NULL;
629     if (cmdKeyLink == NULL) {
630         return;
631     }
632 
633     while (!LOS_ListEmpty(&(cmdKeyLink->list))) {
634         cmdtmp = LOS_DL_LIST_ENTRY(cmdKeyLink->list.pstNext, CmdKeyLink, list);
635         LOS_ListDelete(&cmdtmp->list);
636         (VOID)LOS_MemFree(m_aucSysMem0, cmdtmp);
637     }
638 
639     cmdKeyLink->count = 0;
640     (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink);
641 }
642 
OsShellSysCmdRegister(VOID)643 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellSysCmdRegister(VOID)
644 {
645     UINT32 i;
646     UINT8 *cmdItemGroup = NULL;
647     UINT32 index = ((UINTPTR)(&g_shellcmdEnd) - (UINTPTR)(&g_shellcmd[0])) / sizeof(CmdItem);
648     CmdItemNode *cmdItem = NULL;
649 
650     cmdItemGroup = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, index * sizeof(CmdItemNode));
651     if (cmdItemGroup == NULL) {
652         PRINT_ERR("[%s]System memory allocation failure!\n", __FUNCTION__);
653         return (UINT32)OS_ERROR;
654     }
655 
656     for (i = 0; i < index; ++i) {
657         cmdItem = (CmdItemNode *)(cmdItemGroup + i * sizeof(CmdItemNode));
658         cmdItem->cmd = &g_shellcmd[i];
659         OsCmdAscendingInsert(cmdItem);
660     }
661     g_cmdInfo.listNum += index;
662     return LOS_OK;
663 }
664 
OsShellCmdPush(const CHAR * string,CmdKeyLink * cmdKeyLink)665 LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdPush(const CHAR *string, CmdKeyLink *cmdKeyLink)
666 {
667     CmdKeyLink *cmdNewNode = NULL;
668     UINT32 len;
669 
670     if ((string == NULL) || (strlen(string) == 0)) {
671         return;
672     }
673 
674     len = strlen(string);
675     cmdNewNode = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink) + len + 1);
676     if (cmdNewNode == NULL) {
677         return;
678     }
679 
680     (VOID)memset_s(cmdNewNode, sizeof(CmdKeyLink) + len + 1, 0, sizeof(CmdKeyLink) + len + 1);
681     if (strncpy_s(cmdNewNode->cmdString, len + 1, string, len)) {
682         (VOID)LOS_MemFree(m_aucSysMem0, cmdNewNode);
683         return;
684     }
685 
686     LOS_ListTailInsert(&(cmdKeyLink->list), &(cmdNewNode->list));
687 
688     return;
689 }
690 
OsShellHistoryShow(UINT32 value,ShellCB * shellCB)691 LITE_OS_SEC_TEXT_MINOR VOID OsShellHistoryShow(UINT32 value, ShellCB *shellCB)
692 {
693     CmdKeyLink *cmdtmp = NULL;
694     CmdKeyLink *cmdNode = shellCB->cmdHistoryKeyLink;
695     CmdKeyLink *cmdMask = shellCB->cmdMaskKeyLink;
696     errno_t ret;
697 
698     (VOID)pthread_mutex_lock(&shellCB->historyMutex);
699     if (value == CMD_KEY_DOWN) {
700         if (cmdMask == cmdNode) {
701             goto END;
702         }
703 
704         cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstNext, CmdKeyLink, list);
705         if (cmdtmp != cmdNode) {
706             cmdMask = cmdtmp;
707         } else {
708             goto END;
709         }
710     } else if (value == CMD_KEY_UP) {
711         cmdtmp = LOS_DL_LIST_ENTRY(cmdMask->list.pstPrev, CmdKeyLink, list);
712         if (cmdtmp != cmdNode) {
713             cmdMask = cmdtmp;
714         } else {
715             goto END;
716         }
717     }
718 
719     while (shellCB->shellBufOffset--) {
720         PRINTK("\b \b");
721     }
722     PRINTK("%s", cmdMask->cmdString);
723     shellCB->shellBufOffset = strlen(cmdMask->cmdString);
724     (VOID)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
725     ret = memcpy_s(shellCB->shellBuf, SHOW_MAX_LEN, cmdMask->cmdString, shellCB->shellBufOffset);
726     if (ret != EOK) {
727         PRINT_ERR("%s, %d memcpy failed!\n", __FUNCTION__, __LINE__);
728         goto END;
729     }
730     shellCB->cmdMaskKeyLink = (VOID *)cmdMask;
731 
732 END:
733     (VOID)pthread_mutex_unlock(&shellCB->historyMutex);
734     return;
735 }
736 
OsCmdExec(CmdParsed * cmdParsed,CHAR * cmdStr)737 LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr)
738 {
739     UINT32 ret;
740     CmdCallBackFunc cmdHook = NULL;
741     CmdItemNode *curCmdItem = NULL;
742     UINT32 i;
743     const CHAR *cmdKey = NULL;
744 
745     if ((cmdParsed == NULL) || (cmdStr == NULL) || (strlen(cmdStr) == 0)) {
746         return (UINT32)OS_ERROR;
747     }
748 
749     ret = OsCmdParse(cmdStr, cmdParsed);
750     if (ret != LOS_OK) {
751         goto OUT;
752     }
753 
754     LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(g_cmdInfo.cmdList.list), CmdItemNode, list) {
755         cmdKey = curCmdItem->cmd->cmdKey;
756         if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) &&
757             (strlen(cmdKey) == strlen(cmdParsed->cmdKeyword)) &&
758             (strncmp(cmdKey, (CHAR *)(cmdParsed->cmdKeyword), strlen(cmdKey)) == 0)) {
759             cmdHook = curCmdItem->cmd->cmdHook;
760             break;
761         }
762     }
763 
764     ret = OS_ERROR;
765     if (cmdHook != NULL) {
766         ret = (cmdHook)(cmdParsed->paramCnt, (const CHAR **)cmdParsed->paramArray);
767     }
768 
769 OUT:
770     for (i = 0; i < cmdParsed->paramCnt; i++) {
771         if (cmdParsed->paramArray[i] != NULL) {
772             (VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]);
773             cmdParsed->paramArray[i] = NULL;
774         }
775     }
776 
777     return (UINT32)ret;
778 }
779 
OsCmdInit(VOID)780 LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdInit(VOID)
781 {
782     UINT32 ret;
783     LOS_ListInit(&(g_cmdInfo.cmdList.list));
784     g_cmdInfo.listNum = 0;
785     g_cmdInfo.initMagicFlag = SHELL_INIT_MAGIC_FLAG;
786     ret = LOS_MuxInit(&g_cmdInfo.muxLock, NULL);
787     if (ret != LOS_OK) {
788         PRINT_ERR("Create mutex for shell cmd info failed\n");
789         return OS_ERROR;
790     }
791     return LOS_OK;
792 }
793 
OsCmdItemCreate(CmdType cmdType,const CHAR * cmdKey,UINT32 paraNum,CmdCallBackFunc cmdProc)794 STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
795 {
796     CmdItem *cmdItem = NULL;
797     CmdItemNode *cmdItemNode = NULL;
798 
799     cmdItem = (CmdItem *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItem));
800     if (cmdItem == NULL) {
801         return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
802     }
803     (VOID)memset_s(cmdItem, sizeof(CmdItem), '\0', sizeof(CmdItem));
804 
805     cmdItemNode = (CmdItemNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItemNode));
806     if (cmdItemNode == NULL) {
807         (VOID)LOS_MemFree(m_aucSysMem0, cmdItem);
808         return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
809     }
810     (VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode));
811     cmdItemNode->cmd = cmdItem;
812     cmdItemNode->cmd->cmdHook = cmdProc;
813     cmdItemNode->cmd->paraNum = paraNum;
814     cmdItemNode->cmd->cmdType = cmdType;
815     cmdItemNode->cmd->cmdKey = cmdKey;
816 
817     (VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
818     OsCmdAscendingInsert(cmdItemNode);
819     g_cmdInfo.listNum++;
820     (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
821 
822     return LOS_OK;
823 }
824 
825 /* open API */
osCmdReg(CmdType cmdType,const CHAR * cmdKey,UINT32 paraNum,CmdCallBackFunc cmdProc)826 LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
827 {
828     CmdItemNode *cmdItemNode = NULL;
829 
830     (VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
831     if (g_cmdInfo.initMagicFlag != SHELL_INIT_MAGIC_FLAG) {
832         (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
833         PRINT_ERR("[%s] shell is not yet initialized!\n", __FUNCTION__);
834         return OS_ERRNO_SHELL_NOT_INIT;
835     }
836     (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
837 
838     if ((cmdProc == NULL) || (cmdKey == NULL) ||
839         (cmdType >= CMD_TYPE_BUTT) || (strlen(cmdKey) >= CMD_KEY_LEN) || !strlen(cmdKey)) {
840         return OS_ERRNO_SHELL_CMDREG_PARA_ERROR;
841     }
842 
843     if (paraNum > CMD_MAX_PARAS) {
844         if (paraNum != XARGS) {
845             return OS_ERRNO_SHELL_CMDREG_PARA_ERROR;
846         }
847     }
848 
849     if (OsCmdKeyCheck(cmdKey) != TRUE) {
850         return OS_ERRNO_SHELL_CMDREG_CMD_ERROR;
851     }
852 
853     (VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
854     LOS_DL_LIST_FOR_EACH_ENTRY(cmdItemNode, &(g_cmdInfo.cmdList.list), CmdItemNode, list) {
855         if ((cmdType == cmdItemNode->cmd->cmdType) &&
856             ((strlen(cmdKey) == strlen(cmdItemNode->cmd->cmdKey)) &&
857             (strncmp((CHAR *)(cmdItemNode->cmd->cmdKey), cmdKey, strlen(cmdKey)) == 0))) {
858             (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
859             return OS_ERRNO_SHELL_CMDREG_CMD_EXIST;
860         }
861     }
862     (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);
863 
864     return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc);
865 }
866 
867