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 BSH_CHECK(shell->prompt != NULL, return BSH_INVALID_PARAM, "strdup prompt failed.");
136 }
137 return 0;
138 }
139
BShellEnvOutputByte(BShellHandle handle,char data)140 void BShellEnvOutputByte(BShellHandle handle, char data)
141 {
142 BSH_CHECK(handle != NULL, return, "Invalid shell env");
143 printf("%c", data);
144 (void)fflush(stdout);
145 }
146
BShellEnvOutputResult(BShellHandle handle,int32_t result)147 void BShellEnvOutputResult(BShellHandle handle, int32_t result)
148 {
149 if (result == 0) {
150 return;
151 }
152 printf("result: 0x%08x\r\n", result);
153 (void)fflush(stdout);
154 }
155
BShellEnvOutputParam(BShellHandle handle,char * var)156 static void BShellEnvOutputParam(BShellHandle handle, char *var)
157 {
158 BShellEnvOutput(handle, (var[0] == '$') ? var + 1 : var);
159 BShellEnvOutputString(handle, " = ");
160 BShellEnvOutputString(handle, BShellEnvGetStringParam(handle, var));
161 }
162
BShellEnvBackspace(BShellHandle handle,uint32_t length)163 void BShellEnvBackspace(BShellHandle handle, uint32_t length)
164 {
165 for (uint32_t i = 0; i < length; i++) {
166 BShellEnvOutputString(handle, "\b \b");
167 }
168 }
169
BShellEnvParseParam(BShellEnv * shell)170 static void BShellEnvParseParam(BShellEnv *shell)
171 {
172 uint8_t quotes = 0;
173 uint8_t record = 1;
174 shell->argc = 0;
175 for (uint16_t i = 0; i < shell->length; i++) {
176 char data = *(shell->buffer + i);
177 if ((quotes != 0 || (data != ' ' && data != '\t' && data != ',')) && data != 0) {
178 if (data == '\"') {
179 quotes = quotes ? 0 : 1;
180 }
181 if (record == 1) {
182 BSH_CHECK(shell->argc < BSH_PARAMETER_MAX_NUMBER, return, "argc out of range");
183 shell->args[shell->argc++] = shell->buffer + i;
184 record = 0;
185 }
186 if (*(shell->buffer + i) == '\\' && *(shell->buffer + i + 1) != 0) {
187 i++;
188 }
189 } else {
190 *(shell->buffer + i) = 0;
191 record = 1;
192 }
193 }
194 }
195
BShellEnvExcuteCmd(BShellEnv * shell,BShellCommand * cmd)196 static int32_t BShellEnvExcuteCmd(BShellEnv *shell, BShellCommand *cmd)
197 {
198 return cmd->executer((BShellHandle)shell, shell->argc - cmd->argStart, &shell->args[cmd->argStart]);
199 }
200
BShellEnvHandleEnter(BShellHandle handle,uint8_t data)201 static int32_t BShellEnvHandleEnter(BShellHandle handle, uint8_t data)
202 {
203 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
204 BShellEnv *shell = (BShellEnv *)handle;
205 if (shell->length == 0) {
206 BShellEnvOutputString(shell, "\n");
207 BShellEnvOutputString(handle, shell->prompt);
208 return 0;
209 }
210
211 *(shell->buffer + shell->length++) = 0;
212 BShellEnvParseParam(shell);
213 shell->length = 0;
214 shell->cursor = 0;
215 if (shell->argc == 0) {
216 BShellEnvOutputString(shell, shell->prompt);
217 return 0;
218 }
219
220 BShellEnvOutputString(shell, "\n");
221 if (strcmp((const char *)shell->args[0], "help") == 0) {
222 BShellCmdHelp(handle, shell->argc, shell->args);
223 BShellEnvOutputString(shell, shell->prompt);
224 return 0;
225 }
226 if (shell->args[0][0] == '$') {
227 BShellEnvOutputParam(shell, shell->args[0]);
228 BShellEnvOutputString(shell, shell->prompt);
229 return 0;
230 }
231
232 BShellCommand *cmd = BShellEnvGetCmd(handle, (uint32_t)shell->argc, shell->args);
233 if (cmd != NULL) {
234 int32_t ret = BShellEnvExcuteCmd(shell, cmd);
235 BShellEnvOutputResult(shell, ret);
236 } else {
237 BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST));
238 }
239 BShellEnvOutputString(shell, shell->prompt);
240 return 0;
241 }
242
BShellEnvHandleBackspace(BShellHandle handle,uint8_t code)243 static int32_t BShellEnvHandleBackspace(BShellHandle handle, uint8_t code)
244 {
245 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
246 BShellEnv *shell = (BShellEnv *)handle;
247 if (shell->length == 0) {
248 return 0;
249 }
250 if (shell->cursor == shell->length) {
251 shell->length--;
252 shell->cursor--;
253 shell->buffer[shell->length] = 0;
254 BShellEnvBackspace(handle, 1);
255 } else if (shell->cursor > 0) {
256 for (short i = 0; i < shell->length - shell->cursor; i++) {
257 shell->buffer[shell->cursor + i - 1] = shell->buffer[shell->cursor + i];
258 }
259 shell->length--;
260 shell->cursor--;
261 shell->buffer[shell->length] = 0;
262 BShellEnvOutputByte(shell, '\b');
263 for (short i = shell->cursor; i < shell->length; i++) {
264 BShellEnvOutputByte(shell, shell->buffer[i]);
265 }
266 BShellEnvOutputByte(shell, ' ');
267 for (short i = shell->length - shell->cursor + 1; i > 0; i--) {
268 BShellEnvOutputByte(shell, '\b');
269 }
270 }
271 return 0;
272 }
273
BShellEnvHandleTab(BShellHandle handle,uint8_t code)274 static int32_t BShellEnvHandleTab(BShellHandle handle, uint8_t code)
275 {
276 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
277 return 0;
278 }
279
BShellEnvHandleNormal(BShellHandle handle,uint8_t data)280 static void BShellEnvHandleNormal(BShellHandle handle, uint8_t data)
281 {
282 BSH_CHECK(handle != NULL, return, "Invalid shell env");
283 BShellEnv *shell = (BShellEnv *)handle;
284 if (data == 0) {
285 return;
286 }
287 if (shell->length < BSH_COMMAND_MAX_LENGTH - 1) {
288 if (shell->length == shell->cursor) {
289 shell->buffer[shell->length++] = data;
290 shell->cursor++;
291 BShellEnvOutputByte(shell, data);
292 } else {
293 for (uint16_t i = shell->length - shell->cursor; i > 0; i--) {
294 shell->buffer[shell->cursor + i] = shell->buffer[shell->cursor + i - 1];
295 }
296 shell->buffer[shell->cursor++] = data;
297 shell->buffer[++shell->length] = 0;
298 for (uint16_t i = shell->cursor - 1; i < shell->length; i++) {
299 BShellEnvOutputByte(shell, shell->buffer[i]);
300 }
301 for (uint16_t i = shell->length - shell->cursor; i > 0; i--) {
302 BShellEnvOutputByte(shell, '\b');
303 }
304 }
305 } else {
306 BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_TOO_LONG));
307 BShellEnvOutputString(shell, shell->prompt);
308
309 shell->cursor = shell->length;
310 }
311 }
312
BShellEnvHandleCtrC(BShellHandle handle,uint8_t code)313 static int32_t BShellEnvHandleCtrC(BShellHandle handle, uint8_t code)
314 {
315 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
316 BSH_LOGV("BShellEnvHandleCtrC %d", getpid());
317 #ifndef STARTUP_INIT_TEST
318 kill(getpid(), SIGKILL);
319 #endif
320 return 0;
321 }
322
BShellEnvHandleEsc(BShellHandle handle,uint8_t code)323 static int32_t BShellEnvHandleEsc(BShellHandle handle, uint8_t code)
324 {
325 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
326 BShellEnv *shell = (BShellEnv *)handle;
327 shell->shellState = BSH_ANSI_ESC;
328 return 0;
329 }
330
BShellEnvGetDefaultKey(uint8_t code)331 BShellKey *BShellEnvGetDefaultKey(uint8_t code)
332 {
333 static BShellKey defaultKeys[] = {
334 {BSH_KEY_LF, BShellEnvHandleEnter, NULL},
335 {BSH_KEY_CR, BShellEnvHandleEnter, NULL},
336 {BSH_KEY_TAB, BShellEnvHandleTab, NULL},
337 {BSH_KEY_BACKSPACE, BShellEnvHandleBackspace, NULL},
338 {BSH_KEY_DELETE, BShellEnvHandleBackspace, NULL},
339 {BSH_KEY_CTRLC, BShellEnvHandleCtrC, NULL},
340 {BSH_KEY_ESC, BShellEnvHandleEsc, NULL},
341 };
342 for (size_t i = 0; i < sizeof(defaultKeys) / sizeof(defaultKeys[0]); i++) {
343 if (defaultKeys[i].keyCode == code) {
344 return &defaultKeys[i];
345 }
346 }
347 return NULL;
348 }
349
BShellEnvProcessInput(BShellHandle handle,char data)350 SHELLSTATIC void BShellEnvProcessInput(BShellHandle handle, char data)
351 {
352 BSH_CHECK(handle != NULL, return, "Invalid shell env");
353 BShellEnv *shell = (BShellEnv *)handle;
354 if (shell->shellState == BSH_IN_NORMAL) {
355 BShellKey *key = BShellEnvGetKey(handle, data);
356 if (key != NULL) {
357 key->keyHandle(shell, (uint8_t)data);
358 return;
359 }
360 key = BShellEnvGetDefaultKey(data);
361 if (key != NULL) {
362 key->keyHandle(shell, (uint8_t)data);
363 return;
364 }
365 BShellEnvHandleNormal(shell, data);
366 } else if (shell->shellState == BSH_ANSI_CSI) {
367 switch (data) {
368 case 0x41: // up
369 break;
370 case 0x42: // down
371 break;
372 case 0x43: // ->
373 if (shell->cursor < shell->length) {
374 BShellEnvOutputByte(handle, shell->buffer[shell->cursor]);
375 shell->cursor++;
376 }
377 break;
378 case 0x44: // <-
379 if (shell->cursor > 0) {
380 BShellEnvOutputByte(shell, '\b');
381 shell->cursor--;
382 }
383 break;
384 default:
385 break;
386 }
387 shell->shellState = BSH_IN_NORMAL;
388 } else if (shell->shellState == BSH_ANSI_ESC) {
389 if (data == 0x5B) { // input up/down
390 shell->shellState = BSH_ANSI_CSI;
391 } else {
392 shell->shellState = BSH_IN_NORMAL;
393 }
394 }
395 }
396
BShellEnvLoop(BShellHandle handle)397 void BShellEnvLoop(BShellHandle handle)
398 {
399 BSH_CHECK(handle != NULL, return, "Invalid shell env");
400 BShellEnv *shell = (BShellEnv *)handle;
401 BSH_CHECK(shell->input != NULL, return, "Invalid shell input");
402 while (1) {
403 char data = 0;
404 if (shell->input(&data, 1) == 1) {
405 BShellEnvProcessInput(shell, data);
406 }
407 }
408 }
409
BShellEnvInit(BShellHandle * handle,const BShellInfo * info)410 int32_t BShellEnvInit(BShellHandle *handle, const BShellInfo *info)
411 {
412 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
413 BSH_CHECK(info != NULL && info->prompt != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
414
415 BShellEnv *shell = (BShellEnv *)calloc(1, sizeof(BShellEnv));
416 BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Failed to create shell env");
417 shell->length = 0;
418 shell->cursor = 0;
419 shell->shellState = BSH_IN_NORMAL;
420 shell->input = info->input;
421 shell->prompt = strdup(info->prompt);
422 BSH_CHECK(shell->prompt != NULL, free(shell); return BSH_INVALID_PARAM, "Failed to strdup prompt");
423 shell->command = NULL;
424 shell->param = NULL;
425 shell->keyHandle = NULL;
426 shell->execMode = BSH_EXEC_INDEPENDENT;
427 *handle = (BShellHandle)shell;
428 return 0;
429 }
430
BShellEnvStart(BShellHandle handle)431 int BShellEnvStart(BShellHandle handle)
432 {
433 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
434 BShellEnv *shell = (BShellEnv *)handle;
435 shell->execMode = BSH_EXEC_TASK;
436 BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_SHELL_INFO));
437 BShellEnvOutputString(handle, shell->prompt);
438
439 const CmdInfo infos[] = {
440 {"exit", BShellCmdExit, "exit parameter shell", "exit"},
441 {"help", BShellCmdHelp, "help command", "help"}
442 };
443 for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
444 BShellEnvRegisterCmd(handle, &infos[i]);
445 }
446 return 0;
447 }
448
BShellParamFree(BShellParam * param)449 static void BShellParamFree(BShellParam *param)
450 {
451 if (param->desc != NULL) {
452 free(param->desc);
453 }
454 if (param->type == PARAM_STRING && param->value.string != NULL) {
455 free(param->value.string);
456 }
457 free(param);
458 }
459
BShellCmdFree(BShellCommand * cmd)460 static void BShellCmdFree(BShellCommand *cmd)
461 {
462 if (cmd->desc != NULL) {
463 free(cmd->desc);
464 cmd->desc = NULL;
465 }
466 if (cmd->help != NULL) {
467 free(cmd->help);
468 cmd->help = NULL;
469 }
470 if (cmd->multikey != NULL) {
471 free(cmd->multikey);
472 cmd->multikey = NULL;
473 }
474 free(cmd);
475 }
476
BShellEnvDestory(BShellHandle handle)477 void BShellEnvDestory(BShellHandle handle)
478 {
479 BSH_CHECK(handle != NULL, return, "Invalid shell env");
480 BShellEnv *shell = (BShellEnv *)handle;
481
482 BShellCommand *cmd = shell->command;
483 while (cmd != NULL) {
484 shell->command = cmd->next;
485 BShellCmdFree(cmd);
486 cmd = shell->command;
487 }
488
489 BShellParam *param = shell->param;
490 while (param != NULL) {
491 shell->param = param->next;
492 BShellParamFree(param);
493 param = shell->param;
494 }
495
496 BShellKey *key = shell->keyHandle;
497 while (key != NULL) {
498 shell->keyHandle = key->next;
499 free(key);
500 key = shell->keyHandle;
501 }
502 if (shell->prompt != NULL) {
503 free(shell->prompt);
504 }
505 free(shell);
506 }
507
BShellEnvRegisterCmd(BShellHandle handle,const CmdInfo * cmdInfo)508 int32_t BShellEnvRegisterCmd(BShellHandle handle, const CmdInfo *cmdInfo)
509 {
510 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
511 BSH_CHECK(cmdInfo != NULL && cmdInfo->name != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
512 BSH_CHECK(cmdInfo->executer != NULL, return BSH_INVALID_PARAM, "Invalid cmd executer");
513 BShellEnv *shell = (BShellEnv *)handle;
514 size_t nameLen = strlen(cmdInfo->name) + 1;
515 BShellCommand *cmd = (BShellCommand *)calloc(1, sizeof(BShellCommand) + nameLen);
516 BSH_CHECK(cmd != NULL, return BSH_INVALID_PARAM, "Failed to alloc cmd name %s", cmdInfo->name);
517 cmd->executer = cmdInfo->executer;
518 cmd->argStart = 0;
519 int32_t ret = 0;
520 do {
521 ret = strcpy_s(cmd->name, nameLen, cmdInfo->name);
522 BSH_CHECK(ret == 0, break, "Failed to copy name %s", cmdInfo->name);
523
524 ret = BSH_SYSTEM_ERR;
525 if (cmdInfo->desc != NULL) {
526 cmd->desc = strdup(cmdInfo->desc);
527 BSH_CHECK(cmd->desc != NULL, break, "Failed to copy desc %s", cmdInfo->name);
528 }
529 if (cmdInfo->help != NULL) {
530 cmd->help = strdup(cmdInfo->help);
531 BSH_CHECK(cmd->help != NULL, break, "Failed to copy help %s", cmdInfo->name);
532 }
533 cmd->multikey = NULL;
534 if (cmdInfo->multikey != NULL && strlen(cmdInfo->multikey) > nameLen) {
535 cmd->multikey = strdup(cmdInfo->multikey);
536 BSH_CHECK(cmd->multikey != NULL, break, "Failed to copy multikey %s", cmdInfo->name);
537 int argc = SplitString(cmd->multikey, " ", cmd->multikeys, (int)ARRAY_LENGTH(cmd->multikeys));
538 BSH_CHECK(argc <= (int)ARRAY_LENGTH(cmd->multikeys) && argc > 0, break, "Invalid multikey");
539 cmd->argStart = argc - 1;
540 if (argc == 1) {
541 free(cmd->multikey);
542 cmd->multikey = NULL;
543 }
544 }
545 ret = 0;
546 } while (0);
547 if (ret != 0) {
548 BShellCmdFree(cmd);
549 return ret;
550 }
551 cmd->next = shell->command;
552 shell->command = cmd;
553 return 0;
554 }
555
GetRealCmdName(const char * name)556 static const char *GetRealCmdName(const char *name)
557 {
558 int i = 0;
559 int last = 0;
560 while (*(name + i) != '\0') {
561 if (*(name + i) == '/') {
562 last = i;
563 }
564 i++;
565 }
566 if (last != 0) {
567 return name + last + 1;
568 } else {
569 return name;
570 }
571 }
572
BShellEnvGetCmd(BShellHandle handle,int32_t argc,char * argv[])573 BShellCommand *BShellEnvGetCmd(BShellHandle handle, int32_t argc, char *argv[])
574 {
575 BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
576 BSH_CHECK(argc >= 1, return NULL, "Invalid argc");
577 const char *cmdName = GetRealCmdName(argv[0]);
578 BSH_LOGV("BShellEnvGetCmd %s cmd %s", argv[0], cmdName);
579 BShellEnv *shell = (BShellEnv *)handle;
580 BShellCommand *cmd = shell->command;
581 while (cmd != NULL) {
582 if (strcmp(cmd->name, cmdName) != 0) {
583 cmd = cmd->next;
584 continue;
585 }
586 if (cmd->multikey == NULL) {
587 return cmd;
588 }
589 int32_t i = 0;
590 for (i = 0; i < (int32_t)ARRAY_LENGTH(cmd->multikeys) && i < argc; i++) {
591 if (cmd->multikeys[i] == NULL) {
592 return cmd;
593 }
594 char *tmp = argv[i];
595 if (i == 0) {
596 tmp = (char *)cmdName;
597 }
598 if (strcmp(cmd->multikeys[i], tmp) != 0) {
599 break;
600 }
601 }
602 if (i >= (int32_t)ARRAY_LENGTH(cmd->multikeys)) {
603 return cmd;
604 }
605 if (i >= argc) {
606 if (cmd->multikeys[i] == NULL) {
607 return cmd;
608 }
609 }
610 cmd = cmd->next;
611 }
612 return NULL;
613 }
614
BShellEnvRegisterKeyHandle(BShellHandle handle,uint8_t code,BShellkeyHandle keyHandle)615 int32_t BShellEnvRegisterKeyHandle(BShellHandle handle, uint8_t code, BShellkeyHandle keyHandle)
616 {
617 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
618 BSH_CHECK(keyHandle != NULL, return BSH_INVALID_PARAM, "Invalid cmd name");
619 BShellEnv *shell = (BShellEnv *)handle;
620
621 BShellKey *key = (BShellKey *)calloc(1, sizeof(BShellKey));
622 BSH_CHECK(key != NULL, return BSH_INVALID_PARAM, "Failed to alloc key code %d", code);
623 key->keyCode = code;
624 key->keyHandle = keyHandle;
625 key->next = shell->keyHandle;
626 shell->keyHandle = key;
627 return 0;
628 }
629
BShellEnvGetKey(BShellHandle handle,uint8_t code)630 BShellKey *BShellEnvGetKey(BShellHandle handle, uint8_t code)
631 {
632 BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
633 BShellEnv *shell = (BShellEnv *)handle;
634 BShellKey *key = shell->keyHandle;
635 while (key != NULL) {
636 if (key->keyCode == code) {
637 return key;
638 }
639 key = key->next;
640 }
641 return NULL;
642 }
643
BShellParamSetValue(BShellParam * param,void * value)644 static int32_t BShellParamSetValue(BShellParam *param, void *value)
645 {
646 static uint32_t paramValueLens[] = {
647 sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t), sizeof(char *)
648 };
649 if (param->type == PARAM_STRING) {
650 if (param->value.string != NULL) {
651 free(param->value.string);
652 }
653 param->value.string = strdup((char *)value);
654 BSH_CHECK(param->value.string != NULL, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name);
655 } else if (param->type < PARAM_STRING) {
656 int ret = memcpy_s(¶m->value, sizeof(param->value), value, paramValueLens[param->type]);
657 BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name);
658 }
659 return 0;
660 }
661
BShellEnvSetParam(BShellHandle handle,const char * name,const char * desc,BShellParamType type,void * value)662 int32_t BShellEnvSetParam(BShellHandle handle, const char *name, const char *desc, BShellParamType type, void *value)
663 {
664 BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
665 BSH_CHECK(name != NULL, return BSH_INVALID_PARAM, "Invalid param name");
666 BSH_CHECK(value != NULL, return BSH_INVALID_PARAM, "Invalid cmd value");
667 BSH_CHECK(type <= PARAM_STRING, return BSH_INVALID_PARAM, "Invalid param type");
668 BShellEnv *shell = (BShellEnv *)handle;
669 const BShellParam *tmp = BShellEnvGetParam(handle, name);
670 if (tmp != NULL) {
671 BSH_CHECK(tmp->type <= type, return BSH_INVALID_PARAM, "Invalid param type %d", tmp->type);
672 return BShellParamSetValue((BShellParam *)tmp, value);
673 }
674 int32_t ret = 0;
675 BShellParam *param = NULL;
676 do {
677 size_t nameLen = strlen(name) + 1;
678 param = (BShellParam *)calloc(1, sizeof(BShellParam) + nameLen);
679 BSH_CHECK(param != NULL, return BSH_SYSTEM_ERR, "Failed to alloc cmd name %s", name);
680 param->type = type;
681 ret = strcpy_s(param->name, nameLen, name);
682 BSH_CHECK(ret == 0, break, "Failed to copy name %s", name);
683 if (desc != NULL) {
684 param->desc = strdup(desc);
685 BSH_CHECK(param->desc != NULL, free(param); return BSH_SYSTEM_ERR, "Failed to set desc");
686 }
687 ret = BShellParamSetValue(param, value);
688 BSH_CHECK(ret == 0, break, "Failed set value for %s", name);
689
690 param->next = shell->param;
691 shell->param = param;
692 } while (0);
693 if (ret != 0) {
694 BShellParamFree(param);
695 }
696 return ret;
697 }
698
BShellEnvGetParam(BShellHandle handle,const char * name)699 const BShellParam *BShellEnvGetParam(BShellHandle handle, const char *name)
700 {
701 BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
702 BShellEnv *shell = (BShellEnv *)handle;
703 BShellParam *param = shell->param;
704 while (param != NULL) {
705 if (strcmp(name, param->name) == 0) {
706 return param;
707 }
708 param = param->next;
709 }
710 return NULL;
711 }
712
BShellEnvGetStringParam(BShellHandle handle,const char * name)713 const char *BShellEnvGetStringParam(BShellHandle handle, const char *name)
714 {
715 BSH_CHECK(handle != NULL, return "", "Invalid shell env");
716 const BShellParam *param = BShellEnvGetParam(handle, name);
717 if (param == NULL) {
718 return "";
719 }
720 switch (param->type) {
721 case PARAM_STRING:
722 return param->value.string;
723 default:
724 break;
725 }
726 return "";
727 }
728
BShellEnvGetReservedParam(BShellHandle handle,const char * name)729 const ParamInfo *BShellEnvGetReservedParam(BShellHandle handle, const char *name)
730 {
731 BSH_CHECK(handle != NULL, return NULL, "Invalid shell env");
732 static ParamInfo reservedParams[] = {
733 {PARAM_REVERESD_NAME_CURR_PARAMETER, "current parameter", PARAM_STRING}
734 };
735 for (size_t i = 0; i < sizeof(reservedParams) / sizeof(reservedParams[0]); i++) {
736 if (strcmp(name, reservedParams[i].name) == 0) {
737 return &reservedParams[i];
738 }
739 }
740 return NULL;
741 }
742
BShellEnvDirectExecute(BShellHandle handle,int argc,char * args[])743 int32_t BShellEnvDirectExecute(BShellHandle handle, int argc, char *args[])
744 {
745 BSH_CHECK(handle != NULL, return -1, "Invalid shell env");
746 BShellCommand *cmd = BShellEnvGetCmd(handle, argc, args);
747 if (cmd != NULL) {
748 int32_t ret = cmd->executer(handle, argc - cmd->argStart, &args[cmd->argStart]);
749 BShellEnvOutputResult(handle, ret);
750 } else {
751 if (argc > 1) {
752 BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST));
753 }
754 BShellCmdHelp(handle, argc, args);
755 }
756 return 0;
757 }
758