1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci#include "shell_bas.h"
16d9f0492fSopenharmony_ci#include <fcntl.h>
17d9f0492fSopenharmony_ci#include <signal.h>
18d9f0492fSopenharmony_ci
19d9f0492fSopenharmony_ci#include "init_utils.h"
20d9f0492fSopenharmony_ci#include "shell_utils.h"
21d9f0492fSopenharmony_ci
22d9f0492fSopenharmony_cichar *BShellEnvErrString(BShellHandle handle, int32_t err)
23d9f0492fSopenharmony_ci{
24d9f0492fSopenharmony_ci    static BShellErrInfo shellErrString[] = {
25d9f0492fSopenharmony_ci        {BSH_SHELL_INFO, "\r\n\r\n"
26d9f0492fSopenharmony_ci                        "+=========================================================+\r\n"
27d9f0492fSopenharmony_ci                        "|               Parameter shell v"BSH_VERSION"                    |\r\n"
28d9f0492fSopenharmony_ci                        "+=========================================================+\r\n"
29d9f0492fSopenharmony_ci        },
30d9f0492fSopenharmony_ci        {BSH_CMD_TOO_LONG, "\r\nWarnig: Command is too long\r\n"},
31d9f0492fSopenharmony_ci        {BSH_SHOW_CMD_LIST, "Command list:\r\n"},
32d9f0492fSopenharmony_ci        {BSH_CMD_NOT_EXIST, "Command not found\r\n"}
33d9f0492fSopenharmony_ci    };
34d9f0492fSopenharmony_ci    for (size_t i = 0; i < sizeof(shellErrString) / sizeof(shellErrString[0]); i++) {
35d9f0492fSopenharmony_ci        if ((int32_t)shellErrString[i].err == err) {
36d9f0492fSopenharmony_ci            return shellErrString[i].desc;
37d9f0492fSopenharmony_ci        }
38d9f0492fSopenharmony_ci    }
39d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return "System unknown err", "Invalid shell env");
40d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
41d9f0492fSopenharmony_ci    int len = sprintf_s(shell->data, sizeof(shell->data) - 1, "System unknown err 0x%08x", err);
42d9f0492fSopenharmony_ci    if (len <= 0) {
43d9f0492fSopenharmony_ci        BSH_LOGE("Write shell data size failed.");
44d9f0492fSopenharmony_ci    }
45d9f0492fSopenharmony_ci    return shell->data;
46d9f0492fSopenharmony_ci}
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_cistatic void BShellCmdOutputCmdHelp(BShellHandle handle, BShellCommand *cmd)
49d9f0492fSopenharmony_ci{
50d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, "    ");
51d9f0492fSopenharmony_ci    int32_t spaceLength = BShellEnvOutputString(handle, cmd->help);
52d9f0492fSopenharmony_ci    spaceLength = BSH_CMD_NAME_END - spaceLength;
53d9f0492fSopenharmony_ci    spaceLength = (spaceLength > 0) ? spaceLength : 4; // 4 min
54d9f0492fSopenharmony_ci    do {
55d9f0492fSopenharmony_ci        BShellEnvOutputString(handle, " ");
56d9f0492fSopenharmony_ci    } while (--spaceLength);
57d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, "--");
58d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, cmd->desc);
59d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, "\r\n");
60d9f0492fSopenharmony_ci}
61d9f0492fSopenharmony_ci
62d9f0492fSopenharmony_ciint32_t BShellCmdHelp(BShellHandle handle, int32_t argc, char *argv[])
63d9f0492fSopenharmony_ci{
64d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
65d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
66d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_SHOW_CMD_LIST));
67d9f0492fSopenharmony_ci
68d9f0492fSopenharmony_ci    int show = 0;
69d9f0492fSopenharmony_ci    BShellCommand *cmd = shell->command;
70d9f0492fSopenharmony_ci    while (cmd != NULL) {
71d9f0492fSopenharmony_ci        if ((argc >= 1) &&
72d9f0492fSopenharmony_ci            (strncmp(argv[0], cmd->name, strlen(argv[0])) == 0) &&
73d9f0492fSopenharmony_ci            (strncmp(argv[0], "help", strlen(argv[0])) != 0)) {
74d9f0492fSopenharmony_ci            BShellCmdOutputCmdHelp(handle, cmd);
75d9f0492fSopenharmony_ci            show = 1;
76d9f0492fSopenharmony_ci        }
77d9f0492fSopenharmony_ci        cmd = cmd->next;
78d9f0492fSopenharmony_ci    }
79d9f0492fSopenharmony_ci    if (show) {
80d9f0492fSopenharmony_ci        return 0;
81d9f0492fSopenharmony_ci    }
82d9f0492fSopenharmony_ci    cmd = shell->command;
83d9f0492fSopenharmony_ci    while (cmd != NULL) {
84d9f0492fSopenharmony_ci        BShellCmdOutputCmdHelp(handle, cmd);
85d9f0492fSopenharmony_ci        cmd = cmd->next;
86d9f0492fSopenharmony_ci    }
87d9f0492fSopenharmony_ci    return 0;
88d9f0492fSopenharmony_ci}
89d9f0492fSopenharmony_ci
90d9f0492fSopenharmony_cistatic int32_t BShellCmdExit(BShellHandle handle, int32_t argc, char *argv[])
91d9f0492fSopenharmony_ci{
92d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST
93d9f0492fSopenharmony_ci    kill(getpid(), SIGINT);
94d9f0492fSopenharmony_ci#endif
95d9f0492fSopenharmony_ci    return 0;
96d9f0492fSopenharmony_ci}
97d9f0492fSopenharmony_ci
98d9f0492fSopenharmony_ciint32_t BShellEnvOutput(BShellHandle handle, char *fmt, ...)
99d9f0492fSopenharmony_ci{
100d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
101d9f0492fSopenharmony_ci    va_list list;
102d9f0492fSopenharmony_ci    va_start(list, fmt);
103d9f0492fSopenharmony_ci    int len = vfprintf(stdout, fmt, list);
104d9f0492fSopenharmony_ci    va_end(list);
105d9f0492fSopenharmony_ci    (void)fflush(stdout);
106d9f0492fSopenharmony_ci    return len;
107d9f0492fSopenharmony_ci}
108d9f0492fSopenharmony_ci
109d9f0492fSopenharmony_ciint32_t BShellEnvOutputString(BShellHandle handle, const char *string)
110d9f0492fSopenharmony_ci{
111d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
112d9f0492fSopenharmony_ci    printf("%s", string);
113d9f0492fSopenharmony_ci    (void)fflush(stdout);
114d9f0492fSopenharmony_ci    return strlen(string);
115d9f0492fSopenharmony_ci}
116d9f0492fSopenharmony_ci
117d9f0492fSopenharmony_ciint32_t BShellEnvOutputPrompt(BShellHandle handle, const char *prompt)
118d9f0492fSopenharmony_ci{
119d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
120d9f0492fSopenharmony_ci    BSH_CHECK(prompt != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
121d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
122d9f0492fSopenharmony_ci    if (shell->prompt != NULL) {
123d9f0492fSopenharmony_ci        free(shell->prompt);
124d9f0492fSopenharmony_ci    }
125d9f0492fSopenharmony_ci    size_t promptLen = strlen(prompt);
126d9f0492fSopenharmony_ci    if (promptLen > BSH_CMD_NAME_END) {
127d9f0492fSopenharmony_ci        shell->prompt = strdup(prompt + promptLen - BSH_CMD_NAME_END);
128d9f0492fSopenharmony_ci        if (shell->prompt != NULL) {
129d9f0492fSopenharmony_ci            shell->prompt[0] = '.';
130d9f0492fSopenharmony_ci            shell->prompt[1] = '.';
131d9f0492fSopenharmony_ci            shell->prompt[2] = '.'; // 2 index
132d9f0492fSopenharmony_ci        }
133d9f0492fSopenharmony_ci    } else {
134d9f0492fSopenharmony_ci        shell->prompt = strdup(prompt);
135d9f0492fSopenharmony_ci        BSH_CHECK(shell->prompt != NULL, return BSH_INVALID_PARAM, "strdup prompt failed.");
136d9f0492fSopenharmony_ci    }
137d9f0492fSopenharmony_ci    return 0;
138d9f0492fSopenharmony_ci}
139d9f0492fSopenharmony_ci
140d9f0492fSopenharmony_civoid BShellEnvOutputByte(BShellHandle handle, char data)
141d9f0492fSopenharmony_ci{
142d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return, "Invalid shell env");
143d9f0492fSopenharmony_ci    printf("%c", data);
144d9f0492fSopenharmony_ci    (void)fflush(stdout);
145d9f0492fSopenharmony_ci}
146d9f0492fSopenharmony_ci
147d9f0492fSopenharmony_civoid BShellEnvOutputResult(BShellHandle handle, int32_t result)
148d9f0492fSopenharmony_ci{
149d9f0492fSopenharmony_ci    if (result == 0) {
150d9f0492fSopenharmony_ci        return;
151d9f0492fSopenharmony_ci    }
152d9f0492fSopenharmony_ci    printf("result: 0x%08x\r\n", result);
153d9f0492fSopenharmony_ci    (void)fflush(stdout);
154d9f0492fSopenharmony_ci}
155d9f0492fSopenharmony_ci
156d9f0492fSopenharmony_cistatic void BShellEnvOutputParam(BShellHandle handle, char *var)
157d9f0492fSopenharmony_ci{
158d9f0492fSopenharmony_ci    BShellEnvOutput(handle, (var[0] == '$') ? var + 1 : var);
159d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, " = ");
160d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, BShellEnvGetStringParam(handle, var));
161d9f0492fSopenharmony_ci}
162d9f0492fSopenharmony_ci
163d9f0492fSopenharmony_civoid BShellEnvBackspace(BShellHandle handle, uint32_t length)
164d9f0492fSopenharmony_ci{
165d9f0492fSopenharmony_ci    for (uint32_t i = 0; i < length; i++) {
166d9f0492fSopenharmony_ci        BShellEnvOutputString(handle, "\b \b");
167d9f0492fSopenharmony_ci    }
168d9f0492fSopenharmony_ci}
169d9f0492fSopenharmony_ci
170d9f0492fSopenharmony_cistatic void BShellEnvParseParam(BShellEnv *shell)
171d9f0492fSopenharmony_ci{
172d9f0492fSopenharmony_ci    uint8_t quotes = 0;
173d9f0492fSopenharmony_ci    uint8_t record = 1;
174d9f0492fSopenharmony_ci    shell->argc = 0;
175d9f0492fSopenharmony_ci    for (uint16_t i = 0; i < shell->length; i++) {
176d9f0492fSopenharmony_ci        char data = *(shell->buffer + i);
177d9f0492fSopenharmony_ci        if ((quotes != 0 || (data != ' ' && data != '\t' && data != ',')) && data != 0) {
178d9f0492fSopenharmony_ci            if (data == '\"') {
179d9f0492fSopenharmony_ci                quotes = quotes ? 0 : 1;
180d9f0492fSopenharmony_ci            }
181d9f0492fSopenharmony_ci            if (record == 1) {
182d9f0492fSopenharmony_ci                BSH_CHECK(shell->argc < BSH_PARAMETER_MAX_NUMBER, return, "argc out of range");
183d9f0492fSopenharmony_ci                shell->args[shell->argc++] = shell->buffer + i;
184d9f0492fSopenharmony_ci                record = 0;
185d9f0492fSopenharmony_ci            }
186d9f0492fSopenharmony_ci            if (*(shell->buffer + i) == '\\' && *(shell->buffer + i + 1) != 0) {
187d9f0492fSopenharmony_ci                i++;
188d9f0492fSopenharmony_ci            }
189d9f0492fSopenharmony_ci        } else {
190d9f0492fSopenharmony_ci            *(shell->buffer + i) = 0;
191d9f0492fSopenharmony_ci            record = 1;
192d9f0492fSopenharmony_ci        }
193d9f0492fSopenharmony_ci    }
194d9f0492fSopenharmony_ci}
195d9f0492fSopenharmony_ci
196d9f0492fSopenharmony_cistatic int32_t BShellEnvExcuteCmd(BShellEnv *shell, BShellCommand *cmd)
197d9f0492fSopenharmony_ci{
198d9f0492fSopenharmony_ci    return cmd->executer((BShellHandle)shell, shell->argc - cmd->argStart, &shell->args[cmd->argStart]);
199d9f0492fSopenharmony_ci}
200d9f0492fSopenharmony_ci
201d9f0492fSopenharmony_cistatic int32_t BShellEnvHandleEnter(BShellHandle handle, uint8_t data)
202d9f0492fSopenharmony_ci{
203d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
204d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
205d9f0492fSopenharmony_ci    if (shell->length == 0) {
206d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, "\n");
207d9f0492fSopenharmony_ci        BShellEnvOutputString(handle, shell->prompt);
208d9f0492fSopenharmony_ci        return 0;
209d9f0492fSopenharmony_ci    }
210d9f0492fSopenharmony_ci
211d9f0492fSopenharmony_ci    *(shell->buffer + shell->length++) = 0;
212d9f0492fSopenharmony_ci    BShellEnvParseParam(shell);
213d9f0492fSopenharmony_ci    shell->length = 0;
214d9f0492fSopenharmony_ci    shell->cursor = 0;
215d9f0492fSopenharmony_ci    if (shell->argc == 0) {
216d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, shell->prompt);
217d9f0492fSopenharmony_ci        return 0;
218d9f0492fSopenharmony_ci    }
219d9f0492fSopenharmony_ci
220d9f0492fSopenharmony_ci    BShellEnvOutputString(shell, "\n");
221d9f0492fSopenharmony_ci    if (strcmp((const char *)shell->args[0], "help") == 0) {
222d9f0492fSopenharmony_ci        BShellCmdHelp(handle, shell->argc, shell->args);
223d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, shell->prompt);
224d9f0492fSopenharmony_ci        return 0;
225d9f0492fSopenharmony_ci    }
226d9f0492fSopenharmony_ci    if (shell->args[0][0] == '$') {
227d9f0492fSopenharmony_ci        BShellEnvOutputParam(shell, shell->args[0]);
228d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, shell->prompt);
229d9f0492fSopenharmony_ci        return 0;
230d9f0492fSopenharmony_ci    }
231d9f0492fSopenharmony_ci
232d9f0492fSopenharmony_ci    BShellCommand *cmd = BShellEnvGetCmd(handle, (uint32_t)shell->argc, shell->args);
233d9f0492fSopenharmony_ci    if (cmd != NULL) {
234d9f0492fSopenharmony_ci        int32_t ret = BShellEnvExcuteCmd(shell, cmd);
235d9f0492fSopenharmony_ci        BShellEnvOutputResult(shell, ret);
236d9f0492fSopenharmony_ci    } else {
237d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST));
238d9f0492fSopenharmony_ci    }
239d9f0492fSopenharmony_ci    BShellEnvOutputString(shell, shell->prompt);
240d9f0492fSopenharmony_ci    return 0;
241d9f0492fSopenharmony_ci}
242d9f0492fSopenharmony_ci
243d9f0492fSopenharmony_cistatic int32_t BShellEnvHandleBackspace(BShellHandle handle, uint8_t code)
244d9f0492fSopenharmony_ci{
245d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
246d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
247d9f0492fSopenharmony_ci    if (shell->length == 0) {
248d9f0492fSopenharmony_ci        return 0;
249d9f0492fSopenharmony_ci    }
250d9f0492fSopenharmony_ci    if (shell->cursor == shell->length) {
251d9f0492fSopenharmony_ci        shell->length--;
252d9f0492fSopenharmony_ci        shell->cursor--;
253d9f0492fSopenharmony_ci        shell->buffer[shell->length] = 0;
254d9f0492fSopenharmony_ci        BShellEnvBackspace(handle, 1);
255d9f0492fSopenharmony_ci    } else if (shell->cursor > 0) {
256d9f0492fSopenharmony_ci        for (short i = 0; i < shell->length - shell->cursor; i++) {
257d9f0492fSopenharmony_ci            shell->buffer[shell->cursor + i - 1] = shell->buffer[shell->cursor + i];
258d9f0492fSopenharmony_ci        }
259d9f0492fSopenharmony_ci        shell->length--;
260d9f0492fSopenharmony_ci        shell->cursor--;
261d9f0492fSopenharmony_ci        shell->buffer[shell->length] = 0;
262d9f0492fSopenharmony_ci        BShellEnvOutputByte(shell, '\b');
263d9f0492fSopenharmony_ci        for (short i = shell->cursor; i < shell->length; i++) {
264d9f0492fSopenharmony_ci            BShellEnvOutputByte(shell, shell->buffer[i]);
265d9f0492fSopenharmony_ci        }
266d9f0492fSopenharmony_ci        BShellEnvOutputByte(shell, ' ');
267d9f0492fSopenharmony_ci        for (short i = shell->length - shell->cursor + 1; i > 0; i--) {
268d9f0492fSopenharmony_ci            BShellEnvOutputByte(shell, '\b');
269d9f0492fSopenharmony_ci        }
270d9f0492fSopenharmony_ci    }
271d9f0492fSopenharmony_ci    return 0;
272d9f0492fSopenharmony_ci}
273d9f0492fSopenharmony_ci
274d9f0492fSopenharmony_cistatic int32_t BShellEnvHandleTab(BShellHandle handle, uint8_t code)
275d9f0492fSopenharmony_ci{
276d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
277d9f0492fSopenharmony_ci    return 0;
278d9f0492fSopenharmony_ci}
279d9f0492fSopenharmony_ci
280d9f0492fSopenharmony_cistatic void BShellEnvHandleNormal(BShellHandle handle, uint8_t data)
281d9f0492fSopenharmony_ci{
282d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return, "Invalid shell env");
283d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
284d9f0492fSopenharmony_ci    if (data == 0) {
285d9f0492fSopenharmony_ci        return;
286d9f0492fSopenharmony_ci    }
287d9f0492fSopenharmony_ci    if (shell->length < BSH_COMMAND_MAX_LENGTH - 1) {
288d9f0492fSopenharmony_ci        if (shell->length == shell->cursor) {
289d9f0492fSopenharmony_ci            shell->buffer[shell->length++] = data;
290d9f0492fSopenharmony_ci            shell->cursor++;
291d9f0492fSopenharmony_ci            BShellEnvOutputByte(shell, data);
292d9f0492fSopenharmony_ci        } else {
293d9f0492fSopenharmony_ci            for (uint16_t i = shell->length - shell->cursor; i > 0; i--) {
294d9f0492fSopenharmony_ci                shell->buffer[shell->cursor + i] = shell->buffer[shell->cursor + i - 1];
295d9f0492fSopenharmony_ci            }
296d9f0492fSopenharmony_ci            shell->buffer[shell->cursor++] = data;
297d9f0492fSopenharmony_ci            shell->buffer[++shell->length] = 0;
298d9f0492fSopenharmony_ci            for (uint16_t i = shell->cursor - 1; i < shell->length; i++) {
299d9f0492fSopenharmony_ci                BShellEnvOutputByte(shell, shell->buffer[i]);
300d9f0492fSopenharmony_ci            }
301d9f0492fSopenharmony_ci            for (uint16_t i = shell->length - shell->cursor; i > 0; i--) {
302d9f0492fSopenharmony_ci                BShellEnvOutputByte(shell, '\b');
303d9f0492fSopenharmony_ci            }
304d9f0492fSopenharmony_ci        }
305d9f0492fSopenharmony_ci    } else {
306d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_TOO_LONG));
307d9f0492fSopenharmony_ci        BShellEnvOutputString(shell, shell->prompt);
308d9f0492fSopenharmony_ci
309d9f0492fSopenharmony_ci        shell->cursor = shell->length;
310d9f0492fSopenharmony_ci    }
311d9f0492fSopenharmony_ci}
312d9f0492fSopenharmony_ci
313d9f0492fSopenharmony_cistatic int32_t BShellEnvHandleCtrC(BShellHandle handle, uint8_t code)
314d9f0492fSopenharmony_ci{
315d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
316d9f0492fSopenharmony_ci    BSH_LOGV("BShellEnvHandleCtrC %d", getpid());
317d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST
318d9f0492fSopenharmony_ci    kill(getpid(), SIGKILL);
319d9f0492fSopenharmony_ci#endif
320d9f0492fSopenharmony_ci    return 0;
321d9f0492fSopenharmony_ci}
322d9f0492fSopenharmony_ci
323d9f0492fSopenharmony_cistatic int32_t BShellEnvHandleEsc(BShellHandle handle, uint8_t code)
324d9f0492fSopenharmony_ci{
325d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
326d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
327d9f0492fSopenharmony_ci    shell->shellState = BSH_ANSI_ESC;
328d9f0492fSopenharmony_ci    return 0;
329d9f0492fSopenharmony_ci}
330d9f0492fSopenharmony_ci
331d9f0492fSopenharmony_ciBShellKey *BShellEnvGetDefaultKey(uint8_t code)
332d9f0492fSopenharmony_ci{
333d9f0492fSopenharmony_ci    static BShellKey defaultKeys[] = {
334d9f0492fSopenharmony_ci        {BSH_KEY_LF, BShellEnvHandleEnter, NULL},
335d9f0492fSopenharmony_ci        {BSH_KEY_CR, BShellEnvHandleEnter, NULL},
336d9f0492fSopenharmony_ci        {BSH_KEY_TAB, BShellEnvHandleTab, NULL},
337d9f0492fSopenharmony_ci        {BSH_KEY_BACKSPACE, BShellEnvHandleBackspace, NULL},
338d9f0492fSopenharmony_ci        {BSH_KEY_DELETE, BShellEnvHandleBackspace, NULL},
339d9f0492fSopenharmony_ci        {BSH_KEY_CTRLC, BShellEnvHandleCtrC, NULL},
340d9f0492fSopenharmony_ci        {BSH_KEY_ESC, BShellEnvHandleEsc, NULL},
341d9f0492fSopenharmony_ci    };
342d9f0492fSopenharmony_ci    for (size_t i = 0; i < sizeof(defaultKeys) / sizeof(defaultKeys[0]); i++) {
343d9f0492fSopenharmony_ci        if (defaultKeys[i].keyCode == code) {
344d9f0492fSopenharmony_ci            return &defaultKeys[i];
345d9f0492fSopenharmony_ci        }
346d9f0492fSopenharmony_ci    }
347d9f0492fSopenharmony_ci    return NULL;
348d9f0492fSopenharmony_ci}
349d9f0492fSopenharmony_ci
350d9f0492fSopenharmony_ciSHELLSTATIC void BShellEnvProcessInput(BShellHandle handle, char data)
351d9f0492fSopenharmony_ci{
352d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return, "Invalid shell env");
353d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
354d9f0492fSopenharmony_ci    if (shell->shellState == BSH_IN_NORMAL) {
355d9f0492fSopenharmony_ci        BShellKey *key = BShellEnvGetKey(handle, data);
356d9f0492fSopenharmony_ci        if (key != NULL) {
357d9f0492fSopenharmony_ci            key->keyHandle(shell, (uint8_t)data);
358d9f0492fSopenharmony_ci            return;
359d9f0492fSopenharmony_ci        }
360d9f0492fSopenharmony_ci        key = BShellEnvGetDefaultKey(data);
361d9f0492fSopenharmony_ci        if (key != NULL) {
362d9f0492fSopenharmony_ci            key->keyHandle(shell, (uint8_t)data);
363d9f0492fSopenharmony_ci            return;
364d9f0492fSopenharmony_ci        }
365d9f0492fSopenharmony_ci        BShellEnvHandleNormal(shell, data);
366d9f0492fSopenharmony_ci    } else if (shell->shellState == BSH_ANSI_CSI) {
367d9f0492fSopenharmony_ci        switch (data) {
368d9f0492fSopenharmony_ci            case 0x41:  // up
369d9f0492fSopenharmony_ci                break;
370d9f0492fSopenharmony_ci            case 0x42:  // down
371d9f0492fSopenharmony_ci                break;
372d9f0492fSopenharmony_ci            case 0x43:  // ->
373d9f0492fSopenharmony_ci                if (shell->cursor < shell->length) {
374d9f0492fSopenharmony_ci                    BShellEnvOutputByte(handle, shell->buffer[shell->cursor]);
375d9f0492fSopenharmony_ci                    shell->cursor++;
376d9f0492fSopenharmony_ci                }
377d9f0492fSopenharmony_ci                break;
378d9f0492fSopenharmony_ci            case 0x44:  // <-
379d9f0492fSopenharmony_ci                if (shell->cursor > 0) {
380d9f0492fSopenharmony_ci                    BShellEnvOutputByte(shell, '\b');
381d9f0492fSopenharmony_ci                    shell->cursor--;
382d9f0492fSopenharmony_ci                }
383d9f0492fSopenharmony_ci                break;
384d9f0492fSopenharmony_ci            default:
385d9f0492fSopenharmony_ci                break;
386d9f0492fSopenharmony_ci        }
387d9f0492fSopenharmony_ci        shell->shellState = BSH_IN_NORMAL;
388d9f0492fSopenharmony_ci    } else if (shell->shellState == BSH_ANSI_ESC) {
389d9f0492fSopenharmony_ci        if (data == 0x5B) { // input up/down
390d9f0492fSopenharmony_ci            shell->shellState = BSH_ANSI_CSI;
391d9f0492fSopenharmony_ci        } else {
392d9f0492fSopenharmony_ci            shell->shellState = BSH_IN_NORMAL;
393d9f0492fSopenharmony_ci        }
394d9f0492fSopenharmony_ci    }
395d9f0492fSopenharmony_ci}
396d9f0492fSopenharmony_ci
397d9f0492fSopenharmony_civoid BShellEnvLoop(BShellHandle handle)
398d9f0492fSopenharmony_ci{
399d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return, "Invalid shell env");
400d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
401d9f0492fSopenharmony_ci    BSH_CHECK(shell->input != NULL, return, "Invalid shell input");
402d9f0492fSopenharmony_ci    while (1) {
403d9f0492fSopenharmony_ci        char data = 0;
404d9f0492fSopenharmony_ci        if (shell->input(&data, 1) == 1) {
405d9f0492fSopenharmony_ci            BShellEnvProcessInput(shell, data);
406d9f0492fSopenharmony_ci        }
407d9f0492fSopenharmony_ci    }
408d9f0492fSopenharmony_ci}
409d9f0492fSopenharmony_ci
410d9f0492fSopenharmony_ciint32_t BShellEnvInit(BShellHandle *handle, const BShellInfo *info)
411d9f0492fSopenharmony_ci{
412d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
413d9f0492fSopenharmony_ci    BSH_CHECK(info != NULL && info->prompt != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
414d9f0492fSopenharmony_ci
415d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)calloc(1, sizeof(BShellEnv));
416d9f0492fSopenharmony_ci    BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Failed to create shell env");
417d9f0492fSopenharmony_ci    shell->length = 0;
418d9f0492fSopenharmony_ci    shell->cursor = 0;
419d9f0492fSopenharmony_ci    shell->shellState = BSH_IN_NORMAL;
420d9f0492fSopenharmony_ci    shell->input = info->input;
421d9f0492fSopenharmony_ci    shell->prompt = strdup(info->prompt);
422d9f0492fSopenharmony_ci    BSH_CHECK(shell->prompt != NULL, free(shell); return BSH_INVALID_PARAM, "Failed to strdup prompt");
423d9f0492fSopenharmony_ci    shell->command = NULL;
424d9f0492fSopenharmony_ci    shell->param = NULL;
425d9f0492fSopenharmony_ci    shell->keyHandle = NULL;
426d9f0492fSopenharmony_ci    shell->execMode = BSH_EXEC_INDEPENDENT;
427d9f0492fSopenharmony_ci    *handle = (BShellHandle)shell;
428d9f0492fSopenharmony_ci    return 0;
429d9f0492fSopenharmony_ci}
430d9f0492fSopenharmony_ci
431d9f0492fSopenharmony_ciint BShellEnvStart(BShellHandle handle)
432d9f0492fSopenharmony_ci{
433d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
434d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
435d9f0492fSopenharmony_ci    shell->execMode = BSH_EXEC_TASK;
436d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_SHELL_INFO));
437d9f0492fSopenharmony_ci    BShellEnvOutputString(handle, shell->prompt);
438d9f0492fSopenharmony_ci
439d9f0492fSopenharmony_ci    const CmdInfo infos[] = {
440d9f0492fSopenharmony_ci        {"exit", BShellCmdExit, "exit parameter shell", "exit"},
441d9f0492fSopenharmony_ci        {"help", BShellCmdHelp, "help command", "help"}
442d9f0492fSopenharmony_ci    };
443d9f0492fSopenharmony_ci    for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
444d9f0492fSopenharmony_ci        BShellEnvRegisterCmd(handle, &infos[i]);
445d9f0492fSopenharmony_ci    }
446d9f0492fSopenharmony_ci    return 0;
447d9f0492fSopenharmony_ci}
448d9f0492fSopenharmony_ci
449d9f0492fSopenharmony_cistatic void BShellParamFree(BShellParam *param)
450d9f0492fSopenharmony_ci{
451d9f0492fSopenharmony_ci    if (param->desc != NULL) {
452d9f0492fSopenharmony_ci        free(param->desc);
453d9f0492fSopenharmony_ci    }
454d9f0492fSopenharmony_ci    if (param->type == PARAM_STRING && param->value.string != NULL) {
455d9f0492fSopenharmony_ci        free(param->value.string);
456d9f0492fSopenharmony_ci    }
457d9f0492fSopenharmony_ci    free(param);
458d9f0492fSopenharmony_ci}
459d9f0492fSopenharmony_ci
460d9f0492fSopenharmony_cistatic void BShellCmdFree(BShellCommand *cmd)
461d9f0492fSopenharmony_ci{
462d9f0492fSopenharmony_ci    if (cmd->desc != NULL) {
463d9f0492fSopenharmony_ci        free(cmd->desc);
464d9f0492fSopenharmony_ci        cmd->desc = NULL;
465d9f0492fSopenharmony_ci    }
466d9f0492fSopenharmony_ci    if (cmd->help != NULL) {
467d9f0492fSopenharmony_ci        free(cmd->help);
468d9f0492fSopenharmony_ci        cmd->help = NULL;
469d9f0492fSopenharmony_ci    }
470d9f0492fSopenharmony_ci    if (cmd->multikey != NULL) {
471d9f0492fSopenharmony_ci        free(cmd->multikey);
472d9f0492fSopenharmony_ci        cmd->multikey = NULL;
473d9f0492fSopenharmony_ci    }
474d9f0492fSopenharmony_ci    free(cmd);
475d9f0492fSopenharmony_ci}
476d9f0492fSopenharmony_ci
477d9f0492fSopenharmony_civoid BShellEnvDestory(BShellHandle handle)
478d9f0492fSopenharmony_ci{
479d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return, "Invalid shell env");
480d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
481d9f0492fSopenharmony_ci
482d9f0492fSopenharmony_ci    BShellCommand *cmd = shell->command;
483d9f0492fSopenharmony_ci    while (cmd != NULL) {
484d9f0492fSopenharmony_ci        shell->command = cmd->next;
485d9f0492fSopenharmony_ci        BShellCmdFree(cmd);
486d9f0492fSopenharmony_ci        cmd = shell->command;
487d9f0492fSopenharmony_ci    }
488d9f0492fSopenharmony_ci
489d9f0492fSopenharmony_ci    BShellParam *param = shell->param;
490d9f0492fSopenharmony_ci    while (param != NULL) {
491d9f0492fSopenharmony_ci        shell->param = param->next;
492d9f0492fSopenharmony_ci        BShellParamFree(param);
493d9f0492fSopenharmony_ci        param = shell->param;
494d9f0492fSopenharmony_ci    }
495d9f0492fSopenharmony_ci
496d9f0492fSopenharmony_ci    BShellKey *key = shell->keyHandle;
497d9f0492fSopenharmony_ci    while (key != NULL) {
498d9f0492fSopenharmony_ci        shell->keyHandle = key->next;
499d9f0492fSopenharmony_ci        free(key);
500d9f0492fSopenharmony_ci        key = shell->keyHandle;
501d9f0492fSopenharmony_ci    }
502d9f0492fSopenharmony_ci    if (shell->prompt != NULL) {
503d9f0492fSopenharmony_ci        free(shell->prompt);
504d9f0492fSopenharmony_ci    }
505d9f0492fSopenharmony_ci    free(shell);
506d9f0492fSopenharmony_ci}
507d9f0492fSopenharmony_ci
508d9f0492fSopenharmony_ciint32_t BShellEnvRegisterCmd(BShellHandle handle, const CmdInfo *cmdInfo)
509d9f0492fSopenharmony_ci{
510d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
511d9f0492fSopenharmony_ci    BSH_CHECK(cmdInfo != NULL && cmdInfo->name != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
512d9f0492fSopenharmony_ci    BSH_CHECK(cmdInfo->executer != NULL, return BSH_INVALID_PARAM, "Invalid cmd executer");
513d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
514d9f0492fSopenharmony_ci    size_t nameLen = strlen(cmdInfo->name) + 1;
515d9f0492fSopenharmony_ci    BShellCommand *cmd = (BShellCommand *)calloc(1, sizeof(BShellCommand) + nameLen);
516d9f0492fSopenharmony_ci    BSH_CHECK(cmd != NULL, return BSH_INVALID_PARAM, "Failed to alloc cmd name %s", cmdInfo->name);
517d9f0492fSopenharmony_ci    cmd->executer = cmdInfo->executer;
518d9f0492fSopenharmony_ci    cmd->argStart = 0;
519d9f0492fSopenharmony_ci    int32_t ret = 0;
520d9f0492fSopenharmony_ci    do {
521d9f0492fSopenharmony_ci        ret = strcpy_s(cmd->name, nameLen, cmdInfo->name);
522d9f0492fSopenharmony_ci        BSH_CHECK(ret == 0, break, "Failed to copy name %s", cmdInfo->name);
523d9f0492fSopenharmony_ci
524d9f0492fSopenharmony_ci        ret = BSH_SYSTEM_ERR;
525d9f0492fSopenharmony_ci        if (cmdInfo->desc != NULL) {
526d9f0492fSopenharmony_ci            cmd->desc = strdup(cmdInfo->desc);
527d9f0492fSopenharmony_ci            BSH_CHECK(cmd->desc != NULL, break, "Failed to copy desc %s", cmdInfo->name);
528d9f0492fSopenharmony_ci        }
529d9f0492fSopenharmony_ci        if (cmdInfo->help != NULL) {
530d9f0492fSopenharmony_ci            cmd->help = strdup(cmdInfo->help);
531d9f0492fSopenharmony_ci            BSH_CHECK(cmd->help != NULL, break, "Failed to copy help %s", cmdInfo->name);
532d9f0492fSopenharmony_ci        }
533d9f0492fSopenharmony_ci        cmd->multikey = NULL;
534d9f0492fSopenharmony_ci        if (cmdInfo->multikey != NULL && strlen(cmdInfo->multikey) > nameLen) {
535d9f0492fSopenharmony_ci            cmd->multikey = strdup(cmdInfo->multikey);
536d9f0492fSopenharmony_ci            BSH_CHECK(cmd->multikey != NULL, break, "Failed to copy multikey %s", cmdInfo->name);
537d9f0492fSopenharmony_ci            int argc = SplitString(cmd->multikey, " ", cmd->multikeys, (int)ARRAY_LENGTH(cmd->multikeys));
538d9f0492fSopenharmony_ci            BSH_CHECK(argc <= (int)ARRAY_LENGTH(cmd->multikeys) && argc > 0, break, "Invalid multikey");
539d9f0492fSopenharmony_ci            cmd->argStart = argc - 1;
540d9f0492fSopenharmony_ci            if (argc == 1) {
541d9f0492fSopenharmony_ci                free(cmd->multikey);
542d9f0492fSopenharmony_ci                cmd->multikey = NULL;
543d9f0492fSopenharmony_ci            }
544d9f0492fSopenharmony_ci        }
545d9f0492fSopenharmony_ci        ret = 0;
546d9f0492fSopenharmony_ci    } while (0);
547d9f0492fSopenharmony_ci    if (ret != 0) {
548d9f0492fSopenharmony_ci        BShellCmdFree(cmd);
549d9f0492fSopenharmony_ci        return ret;
550d9f0492fSopenharmony_ci    }
551d9f0492fSopenharmony_ci    cmd->next = shell->command;
552d9f0492fSopenharmony_ci    shell->command = cmd;
553d9f0492fSopenharmony_ci    return 0;
554d9f0492fSopenharmony_ci}
555d9f0492fSopenharmony_ci
556d9f0492fSopenharmony_cistatic const char *GetRealCmdName(const char *name)
557d9f0492fSopenharmony_ci{
558d9f0492fSopenharmony_ci    int i = 0;
559d9f0492fSopenharmony_ci    int last = 0;
560d9f0492fSopenharmony_ci    while (*(name + i) != '\0') {
561d9f0492fSopenharmony_ci        if (*(name + i) == '/') {
562d9f0492fSopenharmony_ci            last = i;
563d9f0492fSopenharmony_ci        }
564d9f0492fSopenharmony_ci        i++;
565d9f0492fSopenharmony_ci    }
566d9f0492fSopenharmony_ci    if (last != 0) {
567d9f0492fSopenharmony_ci        return name + last + 1;
568d9f0492fSopenharmony_ci    } else {
569d9f0492fSopenharmony_ci        return name;
570d9f0492fSopenharmony_ci    }
571d9f0492fSopenharmony_ci}
572d9f0492fSopenharmony_ci
573d9f0492fSopenharmony_ciBShellCommand *BShellEnvGetCmd(BShellHandle handle, int32_t argc, char *argv[])
574d9f0492fSopenharmony_ci{
575d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
576d9f0492fSopenharmony_ci    BSH_CHECK(argc >= 1, return NULL, "Invalid argc");
577d9f0492fSopenharmony_ci    const char *cmdName = GetRealCmdName(argv[0]);
578d9f0492fSopenharmony_ci    BSH_LOGV("BShellEnvGetCmd %s cmd %s", argv[0], cmdName);
579d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
580d9f0492fSopenharmony_ci    BShellCommand *cmd = shell->command;
581d9f0492fSopenharmony_ci    while (cmd != NULL) {
582d9f0492fSopenharmony_ci        if (strcmp(cmd->name, cmdName) != 0) {
583d9f0492fSopenharmony_ci            cmd = cmd->next;
584d9f0492fSopenharmony_ci            continue;
585d9f0492fSopenharmony_ci        }
586d9f0492fSopenharmony_ci        if (cmd->multikey == NULL) {
587d9f0492fSopenharmony_ci            return cmd;
588d9f0492fSopenharmony_ci        }
589d9f0492fSopenharmony_ci        int32_t i = 0;
590d9f0492fSopenharmony_ci        for (i = 0; i < (int32_t)ARRAY_LENGTH(cmd->multikeys) && i < argc; i++) {
591d9f0492fSopenharmony_ci            if (cmd->multikeys[i] == NULL) {
592d9f0492fSopenharmony_ci                return cmd;
593d9f0492fSopenharmony_ci            }
594d9f0492fSopenharmony_ci            char *tmp = argv[i];
595d9f0492fSopenharmony_ci            if (i == 0) {
596d9f0492fSopenharmony_ci                tmp = (char *)cmdName;
597d9f0492fSopenharmony_ci            }
598d9f0492fSopenharmony_ci            if (strcmp(cmd->multikeys[i], tmp) != 0) {
599d9f0492fSopenharmony_ci                break;
600d9f0492fSopenharmony_ci            }
601d9f0492fSopenharmony_ci        }
602d9f0492fSopenharmony_ci        if (i >= (int32_t)ARRAY_LENGTH(cmd->multikeys)) {
603d9f0492fSopenharmony_ci            return cmd;
604d9f0492fSopenharmony_ci        }
605d9f0492fSopenharmony_ci        if (i >= argc) {
606d9f0492fSopenharmony_ci            if (cmd->multikeys[i] == NULL) {
607d9f0492fSopenharmony_ci                return cmd;
608d9f0492fSopenharmony_ci            }
609d9f0492fSopenharmony_ci        }
610d9f0492fSopenharmony_ci        cmd = cmd->next;
611d9f0492fSopenharmony_ci    }
612d9f0492fSopenharmony_ci    return NULL;
613d9f0492fSopenharmony_ci}
614d9f0492fSopenharmony_ci
615d9f0492fSopenharmony_ciint32_t BShellEnvRegisterKeyHandle(BShellHandle handle, uint8_t code, BShellkeyHandle keyHandle)
616d9f0492fSopenharmony_ci{
617d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
618d9f0492fSopenharmony_ci    BSH_CHECK(keyHandle != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
619d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
620d9f0492fSopenharmony_ci
621d9f0492fSopenharmony_ci    BShellKey *key = (BShellKey *)calloc(1, sizeof(BShellKey));
622d9f0492fSopenharmony_ci    BSH_CHECK(key != NULL, return BSH_INVALID_PARAM, "Failed to alloc key code %d", code);
623d9f0492fSopenharmony_ci    key->keyCode = code;
624d9f0492fSopenharmony_ci    key->keyHandle = keyHandle;
625d9f0492fSopenharmony_ci    key->next = shell->keyHandle;
626d9f0492fSopenharmony_ci    shell->keyHandle = key;
627d9f0492fSopenharmony_ci    return 0;
628d9f0492fSopenharmony_ci}
629d9f0492fSopenharmony_ci
630d9f0492fSopenharmony_ciBShellKey *BShellEnvGetKey(BShellHandle handle, uint8_t code)
631d9f0492fSopenharmony_ci{
632d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
633d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
634d9f0492fSopenharmony_ci    BShellKey *key = shell->keyHandle;
635d9f0492fSopenharmony_ci    while (key != NULL) {
636d9f0492fSopenharmony_ci        if (key->keyCode == code) {
637d9f0492fSopenharmony_ci            return key;
638d9f0492fSopenharmony_ci        }
639d9f0492fSopenharmony_ci        key = key->next;
640d9f0492fSopenharmony_ci    }
641d9f0492fSopenharmony_ci    return NULL;
642d9f0492fSopenharmony_ci}
643d9f0492fSopenharmony_ci
644d9f0492fSopenharmony_cistatic int32_t BShellParamSetValue(BShellParam *param, void *value)
645d9f0492fSopenharmony_ci{
646d9f0492fSopenharmony_ci    static uint32_t paramValueLens[] = {
647d9f0492fSopenharmony_ci        sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t), sizeof(char *)
648d9f0492fSopenharmony_ci    };
649d9f0492fSopenharmony_ci    if (param->type == PARAM_STRING) {
650d9f0492fSopenharmony_ci        if (param->value.string != NULL) {
651d9f0492fSopenharmony_ci            free(param->value.string);
652d9f0492fSopenharmony_ci        }
653d9f0492fSopenharmony_ci        param->value.string = strdup((char *)value);
654d9f0492fSopenharmony_ci        BSH_CHECK(param->value.string != NULL, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name);
655d9f0492fSopenharmony_ci    } else if (param->type < PARAM_STRING) {
656d9f0492fSopenharmony_ci        int ret = memcpy_s(&param->value, sizeof(param->value), value, paramValueLens[param->type]);
657d9f0492fSopenharmony_ci        BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name);
658d9f0492fSopenharmony_ci    }
659d9f0492fSopenharmony_ci    return 0;
660d9f0492fSopenharmony_ci}
661d9f0492fSopenharmony_ci
662d9f0492fSopenharmony_ciint32_t BShellEnvSetParam(BShellHandle handle, const char *name, const char *desc, BShellParamType type, void *value)
663d9f0492fSopenharmony_ci{
664d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
665d9f0492fSopenharmony_ci    BSH_CHECK(name != NULL, return BSH_INVALID_PARAM, "Invalid param name");
666d9f0492fSopenharmony_ci    BSH_CHECK(value != NULL, return BSH_INVALID_PARAM, "Invalid cmd value");
667d9f0492fSopenharmony_ci    BSH_CHECK(type <= PARAM_STRING, return BSH_INVALID_PARAM, "Invalid param type");
668d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
669d9f0492fSopenharmony_ci    const BShellParam *tmp = BShellEnvGetParam(handle, name);
670d9f0492fSopenharmony_ci    if (tmp != NULL) {
671d9f0492fSopenharmony_ci        BSH_CHECK(tmp->type <= type, return BSH_INVALID_PARAM, "Invalid param type %d", tmp->type);
672d9f0492fSopenharmony_ci        return BShellParamSetValue((BShellParam *)tmp, value);
673d9f0492fSopenharmony_ci    }
674d9f0492fSopenharmony_ci    int32_t ret = 0;
675d9f0492fSopenharmony_ci    BShellParam *param = NULL;
676d9f0492fSopenharmony_ci    do {
677d9f0492fSopenharmony_ci        size_t nameLen = strlen(name) + 1;
678d9f0492fSopenharmony_ci        param = (BShellParam *)calloc(1, sizeof(BShellParam) + nameLen);
679d9f0492fSopenharmony_ci        BSH_CHECK(param != NULL, return BSH_SYSTEM_ERR, "Failed to alloc cmd name %s", name);
680d9f0492fSopenharmony_ci        param->type = type;
681d9f0492fSopenharmony_ci        ret = strcpy_s(param->name, nameLen, name);
682d9f0492fSopenharmony_ci        BSH_CHECK(ret == 0, break, "Failed to copy name %s", name);
683d9f0492fSopenharmony_ci        if (desc != NULL) {
684d9f0492fSopenharmony_ci            param->desc = strdup(desc);
685d9f0492fSopenharmony_ci            BSH_CHECK(param->desc != NULL, free(param); return BSH_SYSTEM_ERR, "Failed to set desc");
686d9f0492fSopenharmony_ci        }
687d9f0492fSopenharmony_ci        ret = BShellParamSetValue(param, value);
688d9f0492fSopenharmony_ci        BSH_CHECK(ret == 0, break, "Failed set value for %s", name);
689d9f0492fSopenharmony_ci
690d9f0492fSopenharmony_ci        param->next = shell->param;
691d9f0492fSopenharmony_ci        shell->param = param;
692d9f0492fSopenharmony_ci    } while (0);
693d9f0492fSopenharmony_ci    if (ret != 0) {
694d9f0492fSopenharmony_ci        BShellParamFree(param);
695d9f0492fSopenharmony_ci    }
696d9f0492fSopenharmony_ci    return ret;
697d9f0492fSopenharmony_ci}
698d9f0492fSopenharmony_ci
699d9f0492fSopenharmony_ciconst BShellParam *BShellEnvGetParam(BShellHandle handle, const char *name)
700d9f0492fSopenharmony_ci{
701d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
702d9f0492fSopenharmony_ci    BShellEnv *shell = (BShellEnv *)handle;
703d9f0492fSopenharmony_ci    BShellParam *param = shell->param;
704d9f0492fSopenharmony_ci    while (param != NULL) {
705d9f0492fSopenharmony_ci        if (strcmp(name, param->name) == 0) {
706d9f0492fSopenharmony_ci            return param;
707d9f0492fSopenharmony_ci        }
708d9f0492fSopenharmony_ci        param = param->next;
709d9f0492fSopenharmony_ci    }
710d9f0492fSopenharmony_ci    return NULL;
711d9f0492fSopenharmony_ci}
712d9f0492fSopenharmony_ci
713d9f0492fSopenharmony_ciconst char *BShellEnvGetStringParam(BShellHandle handle, const char *name)
714d9f0492fSopenharmony_ci{
715d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return "", "Invalid shell env");
716d9f0492fSopenharmony_ci    const BShellParam *param = BShellEnvGetParam(handle, name);
717d9f0492fSopenharmony_ci    if (param == NULL) {
718d9f0492fSopenharmony_ci        return "";
719d9f0492fSopenharmony_ci    }
720d9f0492fSopenharmony_ci    switch (param->type) {
721d9f0492fSopenharmony_ci        case PARAM_STRING:
722d9f0492fSopenharmony_ci            return param->value.string;
723d9f0492fSopenharmony_ci        default:
724d9f0492fSopenharmony_ci            break;
725d9f0492fSopenharmony_ci    }
726d9f0492fSopenharmony_ci    return "";
727d9f0492fSopenharmony_ci}
728d9f0492fSopenharmony_ci
729d9f0492fSopenharmony_ciconst ParamInfo *BShellEnvGetReservedParam(BShellHandle handle, const char *name)
730d9f0492fSopenharmony_ci{
731d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
732d9f0492fSopenharmony_ci    static ParamInfo reservedParams[] = {
733d9f0492fSopenharmony_ci        {PARAM_REVERESD_NAME_CURR_PARAMETER, "current parameter", PARAM_STRING}
734d9f0492fSopenharmony_ci    };
735d9f0492fSopenharmony_ci    for (size_t i = 0; i < sizeof(reservedParams) / sizeof(reservedParams[0]); i++) {
736d9f0492fSopenharmony_ci        if (strcmp(name, reservedParams[i].name) == 0) {
737d9f0492fSopenharmony_ci            return &reservedParams[i];
738d9f0492fSopenharmony_ci        }
739d9f0492fSopenharmony_ci    }
740d9f0492fSopenharmony_ci    return NULL;
741d9f0492fSopenharmony_ci}
742d9f0492fSopenharmony_ci
743d9f0492fSopenharmony_ciint32_t BShellEnvDirectExecute(BShellHandle handle, int argc, char *args[])
744d9f0492fSopenharmony_ci{
745d9f0492fSopenharmony_ci    BSH_CHECK(handle != NULL, return -1, "Invalid shell env");
746d9f0492fSopenharmony_ci    BShellCommand *cmd = BShellEnvGetCmd(handle, argc, args);
747d9f0492fSopenharmony_ci    if (cmd != NULL) {
748d9f0492fSopenharmony_ci        int32_t ret = cmd->executer(handle, argc - cmd->argStart, &args[cmd->argStart]);
749d9f0492fSopenharmony_ci        BShellEnvOutputResult(handle, ret);
750d9f0492fSopenharmony_ci    } else {
751d9f0492fSopenharmony_ci        if (argc > 1) {
752d9f0492fSopenharmony_ci            BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST));
753d9f0492fSopenharmony_ci        }
754d9f0492fSopenharmony_ci        BShellCmdHelp(handle, argc, args);
755d9f0492fSopenharmony_ci    }
756d9f0492fSopenharmony_ci    return 0;
757d9f0492fSopenharmony_ci}
758