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