• 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 "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 
42 EVENT_CB_S g_shellInputEvent;
43 #define SHELL_CMD_MAX_SIZE 64
44 
45 #define VISIABLE_CHAR(ch) ((ch) > 0x1F && (ch) < 0x7F)
46 
ShellMsgTypeGet(CmdParsed * cmdParsed,const CHAR * cmdType)47 UINT32 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 
GetCmdName(const CHAR * cmdline,UINT32 len)72 CHAR *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 
PreHandleCmdline(const CHAR * input,CHAR ** output,UINT32 * outputlen)112 UINT32 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 
139 END_FREE_SHIFTSTR:
140     free(shiftStr);
141 END:
142     return ret;
143 }
144 
ParseAndExecCmdline(CmdParsed * cmdParsed,const CHAR * cmdline,UINT32 len)145 STATIC 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 
172 OUT:
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 
ExecCmdline(const CHAR * cmdline)182 LITE_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)
ShellTaskEntry(VOID)207 VOID 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 
LosShellInit(VOID)248 LITE_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