1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #define _GNU_SOURCE
33
34 #include "stdlib.h"
35 #include "stdio.h"
36 #include "unistd.h"
37 #include "sys/prctl.h"
38 #include "sys/ioctl.h"
39 #include "syscall.h"
40 #include "sys/wait.h"
41 #include "pthread.h"
42 #include "securec.h"
43 #include "shmsg.h"
44 #include "shell_pri.h"
45 #include "shcmd.h"
46
47 #define CHAR_CTRL_C '\x03'
48 #define CHAR_CTRL_DEL '\x7F'
49
50 #define VISIABLE_CHAR(ch) ((ch) > 0x1F && (ch) < 0x7F)
51
GetCmdline(ShellCB * shellCB)52 char *GetCmdline(ShellCB *shellCB)
53 {
54 CmdKeyLink *cmdkey = shellCB->cmdKeyLink;
55 CmdKeyLink *cmdNode = NULL;
56
57 (void)pthread_mutex_lock(&shellCB->keyMutex);
58 if ((cmdkey == NULL) || SH_ListEmpty(&cmdkey->list)) {
59 (void)pthread_mutex_unlock(&shellCB->keyMutex);
60 return NULL;
61 }
62
63 cmdNode = SH_LIST_ENTRY(cmdkey->list.pstNext, CmdKeyLink, list);
64 if (cmdNode == NULL) {
65 (void)pthread_mutex_unlock(&shellCB->keyMutex);
66 return NULL;
67 }
68
69 SH_ListDelete(&(cmdNode->list));
70 (void)pthread_mutex_unlock(&shellCB->keyMutex);
71
72 if (strlen(cmdNode->cmdString) == 0) {
73 free(cmdNode);
74 return NULL;
75 }
76
77 return cmdNode->cmdString;
78 }
79
ShellSaveHistoryCmd(char * string,ShellCB * shellCB)80 static void ShellSaveHistoryCmd(char *string, ShellCB *shellCB)
81 {
82 CmdKeyLink *cmdHistory = shellCB->cmdHistoryKeyLink;
83 CmdKeyLink *cmdkey = SH_LIST_ENTRY(string, CmdKeyLink, cmdString);
84 CmdKeyLink *cmdNxt = NULL;
85
86 if (*string == '\n') {
87 free(cmdkey);
88 return;
89 }
90
91 (void)pthread_mutex_lock(&shellCB->historyMutex);
92 if (cmdHistory->count != 0) {
93 cmdNxt = SH_LIST_ENTRY(cmdHistory->list.pstPrev, CmdKeyLink, list);
94 if (strcmp(string, cmdNxt->cmdString) == 0) {
95 free((void *)cmdkey);
96 (void)pthread_mutex_unlock(&shellCB->historyMutex);
97 return;
98 }
99 }
100
101 if (cmdHistory->count >= CMD_HISTORY_LEN) {
102 cmdNxt = SH_LIST_ENTRY(cmdHistory->list.pstNext, CmdKeyLink, list);
103 SH_ListDelete(&(cmdNxt->list));
104 SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));
105 free((void *)cmdNxt);
106 (void)pthread_mutex_unlock(&shellCB->historyMutex);
107 return;
108 }
109
110 SH_ListTailInsert(&(cmdHistory->list), &(cmdkey->list));
111 cmdHistory->count++;
112
113 (void)pthread_mutex_unlock(&shellCB->historyMutex);
114 return;
115 }
116
ShellPend(ShellCB * shellCB)117 int ShellPend(ShellCB *shellCB)
118 {
119 if (shellCB == NULL) {
120 return SH_NOK;
121 }
122
123 return sem_wait(&shellCB->shellSem);
124 }
125
ShellNotify(ShellCB * shellCB)126 int ShellNotify(ShellCB *shellCB)
127 {
128 if (shellCB == NULL) {
129 return SH_NOK;
130 }
131
132 return sem_post(&shellCB->shellSem);
133 }
134
135 enum {
136 STAT_NORMAL_KEY,
137 STAT_ESC_KEY,
138 STAT_MULTI_KEY
139 };
140
ShellCmdLineCheckUDRL(const char ch,ShellCB * shellCB)141 static int ShellCmdLineCheckUDRL(const char ch, ShellCB *shellCB)
142 {
143 int ret = SH_OK;
144 if (ch == 0x1b) { /* 0x1b: ESC */
145 shellCB->shellKeyType = STAT_ESC_KEY;
146 return ret;
147 } else if (ch == 0x5b) { /* 0x5b: first Key combination */
148 if (shellCB->shellKeyType == STAT_ESC_KEY) {
149 shellCB->shellKeyType = STAT_MULTI_KEY;
150 return ret;
151 }
152 } else if (ch == 0x41) { /* up */
153 if (shellCB->shellKeyType == STAT_MULTI_KEY) {
154 OsShellHistoryShow(CMD_KEY_UP, shellCB);
155 shellCB->shellKeyType = STAT_NORMAL_KEY;
156 return ret;
157 }
158 } else if (ch == 0x42) { /* down */
159 if (shellCB->shellKeyType == STAT_MULTI_KEY) {
160 shellCB->shellKeyType = STAT_NORMAL_KEY;
161 OsShellHistoryShow(CMD_KEY_DOWN, shellCB);
162 return ret;
163 }
164 } else if (ch == 0x43) { /* right */
165 if (shellCB->shellKeyType == STAT_MULTI_KEY) {
166 shellCB->shellKeyType = STAT_NORMAL_KEY;
167 return ret;
168 }
169 } else if (ch == 0x44) { /* left */
170 if (shellCB->shellKeyType == STAT_MULTI_KEY) {
171 shellCB->shellKeyType = STAT_NORMAL_KEY;
172 return ret;
173 }
174 }
175 return SH_NOK;
176 }
177
ShellTaskNotify(ShellCB * shellCB)178 void ShellTaskNotify(ShellCB *shellCB)
179 {
180 int ret;
181
182 (void)pthread_mutex_lock(&shellCB->keyMutex);
183 OsShellCmdPush(shellCB->shellBuf, shellCB->cmdKeyLink);
184 (void)pthread_mutex_unlock(&shellCB->keyMutex);
185
186 ret = ShellNotify(shellCB);
187 if (ret != SH_OK) {
188 printf("command execute failed, \"%s\"", shellCB->shellBuf);
189 }
190 }
191
ParseEnterKey(OutputFunc outputFunc,ShellCB * shellCB)192 void ParseEnterKey(OutputFunc outputFunc, ShellCB *shellCB)
193 {
194 if ((shellCB == NULL) || (outputFunc == NULL)) {
195 return;
196 }
197
198 if (shellCB->shellBufOffset == 0) {
199 shellCB->shellBuf[shellCB->shellBufOffset] = '\n';
200 shellCB->shellBuf[shellCB->shellBufOffset + 1] = '\0';
201 goto NOTIFY;
202 }
203
204 if (shellCB->shellBufOffset <= (SHOW_MAX_LEN - 1)) {
205 shellCB->shellBuf[shellCB->shellBufOffset] = '\0';
206 }
207 NOTIFY:
208 shellCB->shellBufOffset = 0;
209 ShellTaskNotify(shellCB);
210 }
211
ParseCancelKey(OutputFunc outputFunc,ShellCB * shellCB)212 void ParseCancelKey(OutputFunc outputFunc, ShellCB *shellCB)
213 {
214 if ((shellCB == NULL) || (outputFunc == NULL)) {
215 return;
216 }
217
218 if (shellCB->shellBufOffset <= (SHOW_MAX_LEN - 1)) {
219 shellCB->shellBuf[0] = CHAR_CTRL_C;
220 shellCB->shellBuf[1] = '\0';
221 }
222
223 shellCB->shellBufOffset = 0;
224 ShellTaskNotify(shellCB);
225 }
226
ParseDeleteKey(OutputFunc outputFunc,ShellCB * shellCB)227 void ParseDeleteKey(OutputFunc outputFunc, ShellCB *shellCB)
228 {
229 if ((shellCB == NULL) || (outputFunc == NULL)) {
230 return;
231 }
232
233 if ((shellCB->shellBufOffset > 0) && (shellCB->shellBufOffset <= (SHOW_MAX_LEN - 1))) {
234 shellCB->shellBuf[shellCB->shellBufOffset - 1] = '\0';
235 shellCB->shellBufOffset--;
236 outputFunc("\b \b");
237 }
238 }
239
ParseTabKey(OutputFunc outputFunc,ShellCB * shellCB)240 void ParseTabKey(OutputFunc outputFunc, ShellCB *shellCB)
241 {
242 int ret;
243
244 if ((shellCB == NULL) || (outputFunc == NULL)) {
245 return;
246 }
247
248 if ((shellCB->shellBufOffset > 0) && (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1))) {
249 ret = OsTabCompletion(shellCB->shellBuf, &shellCB->shellBufOffset);
250 if (ret > 1) {
251 outputFunc(SHELL_PROMPT"%s", shellCB->shellBuf);
252 }
253 }
254 }
255
ParseNormalChar(char ch,OutputFunc outputFunc,ShellCB * shellCB)256 void ParseNormalChar(char ch, OutputFunc outputFunc, ShellCB *shellCB)
257 {
258 if ((shellCB == NULL) || (outputFunc == NULL) || !VISIABLE_CHAR(ch)) {
259 return;
260 }
261
262 if ((ch != '\0') && (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1))) {
263 shellCB->shellBuf[shellCB->shellBufOffset] = ch;
264 shellCB->shellBufOffset++;
265 outputFunc("%c", ch);
266 }
267
268 shellCB->shellKeyType = STAT_NORMAL_KEY;
269 }
270
ShellCmdLineParse(char c,OutputFunc outputFunc,ShellCB * shellCB)271 void ShellCmdLineParse(char c, OutputFunc outputFunc, ShellCB *shellCB)
272 {
273 const char ch = c;
274 int ret;
275
276 if ((shellCB->shellBufOffset == 0) && (ch != '\n') && (ch != CHAR_CTRL_C) && (ch != '\0')) {
277 (void)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
278 }
279
280 switch (ch) {
281 case '\r':
282 case '\n': /* enter */
283 ParseEnterKey(outputFunc, shellCB);
284 break;
285 case CHAR_CTRL_C: /* ctrl + c */
286 ParseCancelKey(outputFunc, shellCB);
287 break;
288 case '\b': /* backspace */
289 case CHAR_CTRL_DEL: /* delete(0x7F) */
290 ParseDeleteKey(outputFunc, shellCB);
291 break;
292 case '\t': /* tab */
293 ParseTabKey(outputFunc, shellCB);
294 break;
295 default:
296 /* parse the up/down/right/left key */
297 ret = ShellCmdLineCheckUDRL(ch, shellCB);
298 if (ret == SH_OK) {
299 return;
300 }
301 ParseNormalChar(ch, outputFunc, shellCB);
302 break;
303 }
304
305 return;
306 }
307
ShellMsgNameGet(CmdParsed * cmdParsed,const char * cmdType)308 unsigned int ShellMsgNameGet(CmdParsed *cmdParsed, const char *cmdType)
309 {
310 (void)cmdParsed;
311 (void)cmdType;
312 return SH_ERROR;
313 }
314
GetCmdName(const char * cmdline,unsigned int len)315 char *GetCmdName(const char *cmdline, unsigned int len)
316 {
317 unsigned int loop;
318 const char *tmpStr = NULL;
319 bool quotes = FALSE;
320 char *cmdName = NULL;
321 if (cmdline == NULL) {
322 return NULL;
323 }
324
325 cmdName = (char *)malloc(len + 1);
326 if (cmdName == NULL) {
327 printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
328 return NULL;
329 }
330
331 /* Scan the 'cmdline' string for command */
332 /* Notice: Command string must not have any special name */
333 for (tmpStr = cmdline, loop = 0; (*tmpStr != '\0') && (loop < len); ) {
334 /* If reach a double quotes, switch the quotes matching status */
335 if (*tmpStr == '\"') {
336 SWITCH_QUOTES_STATUS(quotes);
337 /* Ignore the double quote character itself */
338 tmpStr++;
339 continue;
340 }
341 /* If detected a space which the quotes matching status is false */
342 /* which said has detected the first space for separator, finish this scan operation */
343 if ((*tmpStr == ' ') && (QUOTES_STATUS_CLOSE(quotes))) {
344 break;
345 }
346 cmdName[loop] = *tmpStr++;
347 loop++;
348 }
349 cmdName[loop] = '\0';
350
351 return cmdName;
352 }
353
ChildExec(const char * cmdName,char * const paramArray[],bool foreground)354 void ChildExec(const char *cmdName, char *const paramArray[], bool foreground)
355 {
356 int ret;
357 pid_t gid;
358
359 ret = setpgrp();
360 if (ret == -1) {
361 exit(1);
362 }
363
364 gid = getpgrp();
365 if (gid < 0) {
366 printf("get group id failed, pgrpid %d, errno %d\n", gid, errno);
367 exit(1);
368 }
369
370 if (!foreground) {
371 ret = tcsetpgrp(STDIN_FILENO, gid);
372 if (ret != 0) {
373 printf("tcsetpgrp failed, errno %d\n", errno);
374 exit(1);
375 }
376 }
377
378 ret = execve(cmdName, paramArray, NULL);
379 if (ret == -1) {
380 perror("execve");
381 exit(-1);
382 }
383 }
384
CheckExit(const char * cmdName,const CmdParsed * cmdParsed)385 int CheckExit(const char *cmdName, const CmdParsed *cmdParsed)
386 {
387 int ret = 0;
388
389 if (strlen(cmdName) != CMD_EXIT_COMMAND_BYTES || strncmp(cmdName, CMD_EXIT_COMMAND, CMD_EXIT_COMMAND_BYTES) != 0) {
390 return 0;
391 }
392
393 if (cmdParsed->paramCnt > 1) {
394 printf("exit: too many arguments\n");
395 return -1;
396 }
397 if (cmdParsed->paramCnt == 1) {
398 char *p = NULL;
399 ret = strtol(cmdParsed->paramArray[0], &p, CMD_EXIT_CODE_BASE_DEC);
400 if (*p != '\0') {
401 printf("exit: bad number: %s\n", cmdParsed->paramArray[0]);
402 return -1;
403 }
404 }
405
406 exit(ret);
407 }
408
DoCmdExec(const char * cmdName,const char * cmdline,unsigned int len,CmdParsed * cmdParsed)409 static void DoCmdExec(const char *cmdName, const char *cmdline, unsigned int len, CmdParsed *cmdParsed)
410 {
411 bool foreground = FALSE;
412 int ret;
413 pid_t forkPid;
414
415 if (strncmp(cmdline, CMD_EXEC_COMMAND, CMD_EXEC_COMMAND_BYTES) == 0) {
416 if ((cmdParsed->paramCnt > 1) && (strcmp(cmdParsed->paramArray[cmdParsed->paramCnt - 1], "&") == 0)) {
417 free(cmdParsed->paramArray[cmdParsed->paramCnt - 1]);
418 cmdParsed->paramArray[cmdParsed->paramCnt - 1] = NULL;
419 cmdParsed->paramCnt--;
420 foreground = TRUE;
421 }
422
423 forkPid = fork();
424 if (forkPid < 0) {
425 printf("Failed to fork from shell\n");
426 return;
427 } else if (forkPid == 0) {
428 ChildExec(cmdParsed->paramArray[0], cmdParsed->paramArray, foreground);
429 } else {
430 if (!foreground) {
431 (void)waitpid(forkPid, 0, 0);
432 }
433 ret = tcsetpgrp(STDIN_FILENO, getpid());
434 if (ret != 0) {
435 printf("tcsetpgrp failed, errno %d\n", errno);
436 }
437 }
438 } else {
439 if (CheckExit(cmdName, cmdParsed) < 0) {
440 return;
441 }
442 (void)syscall(__NR_shellexec, cmdName, cmdline);
443 }
444 }
445
ParseAndExecCmdline(CmdParsed * cmdParsed,const char * cmdline,unsigned int len)446 static void ParseAndExecCmdline(CmdParsed *cmdParsed, const char *cmdline, unsigned int len)
447 {
448 int i;
449 unsigned int ret;
450 char shellWorkingDirectory[PATH_MAX + 1] = { 0 };
451 char *cmdlineOrigin = NULL;
452 char *cmdName = NULL;
453
454 cmdlineOrigin = strdup(cmdline);
455 if (cmdlineOrigin == NULL) {
456 printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
457 return;
458 }
459
460 cmdName = GetCmdName(cmdline, len);
461 if (cmdName == NULL) {
462 free(cmdlineOrigin);
463 printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
464 return;
465 }
466
467 ret = OsCmdParse((char *)cmdline, cmdParsed);
468 if (ret != SH_OK) {
469 printf("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__);
470 goto OUT;
471 }
472
473 DoCmdExec(cmdName, cmdlineOrigin, len, cmdParsed);
474
475 if (getcwd(shellWorkingDirectory, PATH_MAX) != NULL) {
476 (void)OsShellSetWorkingDirectory(shellWorkingDirectory, (PATH_MAX + 1));
477 }
478
479 OUT:
480 for (i = 0; i < cmdParsed->paramCnt; i++) {
481 if (cmdParsed->paramArray[i] != NULL) {
482 free(cmdParsed->paramArray[i]);
483 cmdParsed->paramArray[i] = NULL;
484 }
485 }
486 free(cmdName);
487 free(cmdlineOrigin);
488 }
489
PreHandleCmdline(const char * input,char ** output,unsigned int * outputlen)490 unsigned int PreHandleCmdline(const char *input, char **output, unsigned int *outputlen)
491 {
492 unsigned int shiftLen, execLen, newLen;
493 unsigned int removeLen = strlen("./"); /* "./" needs to be removed if it exists */
494 unsigned int ret;
495 char *newCmd = NULL;
496 char *execCmd = CMD_EXEC_COMMAND;
497 const char *cmdBuf = input;
498 unsigned int cmdBufLen = strlen(cmdBuf);
499 char *shiftStr = (char *)malloc(cmdBufLen + 1);
500 errno_t err;
501
502 if (shiftStr == NULL) {
503 printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
504 return SH_NOK;
505 }
506 (void)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1);
507
508 /* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */
509 ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1);
510 shiftLen = strlen(shiftStr);
511 if ((ret != SH_OK) || (shiftLen == 0)) {
512 ret = SH_NOK;
513 goto END_FREE_SHIFTSTR;
514 }
515 *output = shiftStr;
516 *outputlen = shiftLen;
517
518 /* Check and parse "./", located at the first two characters of the cmd */
519 if ((shiftLen > removeLen) && (shiftStr[0] == '.') && (shiftStr[1] == '/')) {
520 execLen = strlen(execCmd);
521 newLen = execLen + shiftLen - removeLen; /* i.e., newLen - execLen == shiftLen - removeLen */
522 newCmd = (char *)malloc(newLen + 1);
523 if (newCmd == NULL) {
524 ret = SH_NOK;
525 printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
526 goto END_FREE_SHIFTSTR;
527 }
528
529 err = memcpy_s(newCmd, newLen, execCmd, execLen);
530 if (err != EOK) {
531 printf("memcpy_s failure in %s[%d]\n", __FUNCTION__, __LINE__);
532 ret = SH_NOK;
533 goto END_FREE_NEWCMD;
534 }
535
536 err = memcpy_s(newCmd + execLen, newLen - execLen, shiftStr + removeLen, shiftLen - removeLen);
537 if (err != EOK) {
538 printf("memcpy_s failure in %s[%d]\n", __FUNCTION__, __LINE__);
539 ret = SH_NOK;
540 goto END_FREE_NEWCMD;
541 }
542 newCmd[newLen] = '\0';
543
544 *output = newCmd;
545 *outputlen = newLen;
546 ret = SH_OK;
547 goto END_FREE_SHIFTSTR;
548 } else {
549 ret = SH_OK;
550 goto END;
551 }
552 END_FREE_NEWCMD:
553 free(newCmd);
554 END_FREE_SHIFTSTR:
555 free(shiftStr);
556 END:
557 return ret;
558 }
559
ExecCmdline(const char * cmdline)560 static void ExecCmdline(const char *cmdline)
561 {
562 unsigned int ret;
563 char *output = NULL;
564 unsigned int outputlen;
565 CmdParsed cmdParsed;
566
567 if (cmdline == NULL) {
568 return;
569 }
570
571 /* strip out unnecessary characters */
572 ret = PreHandleCmdline(cmdline, &output, &outputlen);
573 if (ret == SH_NOK) {
574 return;
575 }
576
577 (void)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed));
578 ParseAndExecCmdline(&cmdParsed, output, outputlen);
579 free(output);
580 }
581
ShellCmdProcess(ShellCB * shellCB)582 static void ShellCmdProcess(ShellCB *shellCB)
583 {
584 while (1) {
585 char *buf = GetCmdline(shellCB);
586 if (buf == NULL) {
587 break;
588 }
589 if (buf[0] == CHAR_CTRL_C) {
590 printf("^C");
591 buf[0] = '\n';
592 }
593 printf("\n");
594 ExecCmdline(buf);
595 ShellSaveHistoryCmd(buf, shellCB);
596 shellCB->cmdMaskKeyLink = shellCB->cmdHistoryKeyLink;
597 printf(SHELL_PROMPT);
598 }
599 }
600
ShellTask(void * argv)601 void *ShellTask(void *argv)
602 {
603 int ret;
604 ShellCB *shellCB = (ShellCB *)argv;
605
606 if (shellCB == NULL) {
607 return NULL;
608 }
609
610 ret = prctl(PR_SET_NAME, "ShellTask");
611 if (ret != SH_OK) {
612 return NULL;
613 }
614
615 printf(SHELL_PROMPT);
616 while (1) {
617 ret = ShellPend(shellCB);
618 if (ret == SH_OK) {
619 ShellCmdProcess(shellCB);
620 } else if (ret != SH_OK) {
621 break;
622 }
623 }
624
625 return NULL;
626 }
627
ShellTaskInit(ShellCB * shellCB)628 int ShellTaskInit(ShellCB *shellCB)
629 {
630 unsigned int ret;
631 size_t stackSize = SHELL_TASK_STACKSIZE;
632 void *arg = NULL;
633 pthread_attr_t attr;
634
635 if (shellCB == NULL) {
636 return SH_NOK;
637 }
638
639 ret = pthread_attr_init(&attr);
640 if (ret != SH_OK) {
641 return SH_NOK;
642 }
643
644 pthread_attr_setstacksize(&attr, stackSize);
645 arg = (void *)shellCB;
646 ret = pthread_create(&shellCB->shellTaskHandle, &attr, &ShellTask, arg);
647 if (ret != SH_OK) {
648 return SH_NOK;
649 }
650
651 return ret;
652 }
653
ShellKernelReg(unsigned int shellHandle)654 static int ShellKernelReg(unsigned int shellHandle)
655 {
656 return ioctl(STDIN_FILENO, CONSOLE_CONTROL_REG_USERTASK, shellHandle);
657 }
658
ShellEntry(ShellCB * shellCB)659 void ShellEntry(ShellCB *shellCB)
660 {
661 char ch;
662 int ret;
663 int n;
664 pid_t tid = syscall(__NR_gettid);
665
666 if (shellCB == NULL) {
667 return;
668 }
669
670 (void)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
671
672 ret = ShellKernelReg((int)tid);
673 if (ret != 0) {
674 printf("another shell is already running!\n");
675 exit(-1);
676 }
677
678 while (1) {
679 n = read(0, &ch, 1);
680 if (n == 1) {
681 ShellCmdLineParse(ch, (OutputFunc)printf, shellCB);
682 }
683 }
684 return;
685 }
686