• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #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[])354 void ChildExec(const char *cmdName, char *const paramArray[])
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     ret = tcsetpgrp(STDIN_FILENO, gid);
371     if (ret != 0) {
372         printf("tcsetpgrp failed, errno %d\n", errno);
373         exit(1);
374     }
375 
376     ret = execve(cmdName, paramArray, NULL);
377     if (ret == -1) {
378         perror("execve");
379         exit(-1);
380     }
381 }
382 
CheckExit(const char * cmdName,const CmdParsed * cmdParsed)383 int CheckExit(const char *cmdName, const CmdParsed *cmdParsed)
384 {
385     int ret = 0;
386 
387     if (strlen(cmdName) != CMD_EXIT_COMMAND_BYTES || strncmp(cmdName, CMD_EXIT_COMMAND, CMD_EXIT_COMMAND_BYTES) != 0) {
388         return 0;
389     }
390 
391     if (cmdParsed->paramCnt > 1) {
392         printf("exit: too many arguments\n");
393         return -1;
394     }
395     if (cmdParsed->paramCnt == 1) {
396         char *p = NULL;
397         ret = strtol(cmdParsed->paramArray[0], &p, CMD_EXIT_CODE_BASE_DEC);
398         if (*p != '\0') {
399             printf("exit: bad number: %s\n", cmdParsed->paramArray[0]);
400             return -1;
401         }
402     }
403 
404     exit(ret);
405 }
406 
DoCmdExec(const char * cmdName,const char * cmdline,unsigned int len,const CmdParsed * cmdParsed)407 static void DoCmdExec(const char *cmdName, const char *cmdline, unsigned int len, const CmdParsed *cmdParsed)
408 {
409     int ret;
410     pid_t forkPid;
411 
412     if (strncmp(cmdline, CMD_EXEC_COMMAND, CMD_EXEC_COMMAND_BYTES) == 0) {
413         forkPid = fork();
414         if (forkPid < 0) {
415             printf("Faild to fork from shell\n");
416             return;
417         } else if (forkPid == 0) {
418             ChildExec(cmdParsed->paramArray[0], cmdParsed->paramArray);
419         } else {
420             waitpid(forkPid, 0, 0);
421             ret = tcsetpgrp(STDIN_FILENO, getpid());
422             if (ret != 0) {
423                 printf("tcsetpgrp failed, errno %d\n", errno);
424             }
425         }
426     } else {
427         if (CheckExit(cmdName, cmdParsed) < 0) {
428             return;
429         }
430         (void)syscall(__NR_shellexec, cmdName, cmdline);
431     }
432 }
433 
ParseAndExecCmdline(CmdParsed * cmdParsed,const char * cmdline,unsigned int len)434 static void ParseAndExecCmdline(CmdParsed *cmdParsed, const char *cmdline, unsigned int len)
435 {
436     int i;
437     unsigned int ret;
438     char shellWorkingDirectory[PATH_MAX + 1] = { 0 };
439     char *cmdlineOrigin = NULL;
440     char *cmdName = NULL;
441 
442     cmdlineOrigin = strdup(cmdline);
443     if (cmdlineOrigin == NULL) {
444         printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
445         return;
446     }
447 
448     cmdName = GetCmdName(cmdline, len);
449     if (cmdName == NULL) {
450         free(cmdlineOrigin);
451         printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
452         return;
453     }
454 
455     ret = OsCmdParse((char *)cmdline, cmdParsed);
456     if (ret != SH_OK) {
457         printf("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__);
458         goto OUT;
459     }
460 
461     DoCmdExec(cmdName, cmdlineOrigin, len, cmdParsed);
462 
463     if (getcwd(shellWorkingDirectory, PATH_MAX) != NULL) {
464         (void)OsShellSetWorkingDirectory(shellWorkingDirectory, (PATH_MAX + 1));
465     }
466 
467 OUT:
468     for (i = 0; i < cmdParsed->paramCnt; i++) {
469         if (cmdParsed->paramArray[i] != NULL) {
470             free(cmdParsed->paramArray[i]);
471             cmdParsed->paramArray[i] = NULL;
472         }
473     }
474     free(cmdName);
475     free(cmdlineOrigin);
476 }
477 
PreHandleCmdline(const char * input,char ** output,unsigned int * outputlen)478 unsigned int PreHandleCmdline(const char *input, char **output, unsigned int *outputlen)
479 {
480     unsigned int shiftLen, execLen, newLen;
481     unsigned int removeLen = strlen("./"); /* "./" needs to be removed if it exists */
482     unsigned int ret;
483     char *newCmd = NULL;
484     char *execCmd = CMD_EXEC_COMMAND;
485     const char *cmdBuf = input;
486     unsigned int cmdBufLen = strlen(cmdBuf);
487     char *shiftStr = (char *)malloc(cmdBufLen + 1);
488     errno_t err;
489 
490     if (shiftStr == NULL) {
491         printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
492         return SH_NOK;
493     }
494     (void)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1);
495 
496     /* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */
497     ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1);
498     shiftLen = strlen(shiftStr);
499     if ((ret != SH_OK) || (shiftLen == 0)) {
500         ret = SH_NOK;
501         goto END_FREE_SHIFTSTR;
502     }
503     *output = shiftStr;
504     *outputlen = shiftLen;
505 
506     /* Check and parse "./", located at the first two characters of the cmd */
507     if ((shiftLen > removeLen) && (shiftStr[0] == '.') && (shiftStr[1] == '/')) {
508         execLen = strlen(execCmd);
509         newLen = execLen + shiftLen - removeLen; /* i.e., newLen - execLen == shiftLen - removeLen */
510         newCmd = (char *)malloc(newLen + 1);
511         if (newCmd == NULL) {
512             ret = SH_NOK;
513             printf("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
514             goto END_FREE_SHIFTSTR;
515         }
516 
517         err = memcpy_s(newCmd, newLen, execCmd, execLen);
518         if (err != EOK) {
519             printf("memcpy_s failure in %s[%d]\n", __FUNCTION__, __LINE__);
520             ret = SH_NOK;
521             goto END_FREE_NEWCMD;
522         }
523 
524         err = memcpy_s(newCmd + execLen, newLen - execLen, shiftStr + removeLen, shiftLen - removeLen);
525         if (err != EOK) {
526             printf("memcpy_s failure in %s[%d]\n", __FUNCTION__, __LINE__);
527             ret = SH_NOK;
528             goto END_FREE_NEWCMD;
529         }
530         newCmd[newLen] = '\0';
531 
532         *output = newCmd;
533         *outputlen = newLen;
534         ret = SH_OK;
535         goto END_FREE_SHIFTSTR;
536     } else {
537         ret = SH_OK;
538         goto END;
539     }
540 END_FREE_NEWCMD:
541     free(newCmd);
542 END_FREE_SHIFTSTR:
543     free(shiftStr);
544 END:
545     return ret;
546 }
547 
ExecCmdline(const char * cmdline)548 static void ExecCmdline(const char *cmdline)
549 {
550     unsigned int ret;
551     char *output = NULL;
552     unsigned int outputlen;
553     CmdParsed cmdParsed;
554 
555     if (cmdline == NULL) {
556         return;
557     }
558 
559     /* strip out unnecessary characters */
560     ret = PreHandleCmdline(cmdline, &output, &outputlen);
561     if (ret == SH_NOK) {
562         return;
563     }
564 
565     (void)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed));
566     ParseAndExecCmdline(&cmdParsed, output, outputlen);
567     free(output);
568 }
569 
RecycleZombieChild(void)570 void RecycleZombieChild(void)
571 {
572     while (waitpid(-1, NULL, WNOHANG) > 0) {
573         continue;
574     }
575 }
576 
ShellCmdProcess(ShellCB * shellCB)577 static void ShellCmdProcess(ShellCB *shellCB)
578 {
579     char *buf = NULL;
580     while (1) {
581         /* recycle zombine child process */
582         RecycleZombieChild();
583         buf = GetCmdline(shellCB);
584         if (buf == NULL) {
585             break;
586         }
587         if (buf[0] == CHAR_CTRL_C) {
588             printf("^C");
589             buf[0] = '\n';
590         }
591         printf("\n");
592         ExecCmdline(buf);
593         ShellSaveHistoryCmd(buf, shellCB);
594         shellCB->cmdMaskKeyLink = shellCB->cmdHistoryKeyLink;
595         printf(SHELL_PROMPT);
596     }
597 }
598 
ShellTask(void * argv)599 void *ShellTask(void *argv)
600 {
601     int ret;
602     ShellCB *shellCB = (ShellCB *)argv;
603 
604     if (shellCB == NULL) {
605         return NULL;
606     }
607 
608     ret = prctl(PR_SET_NAME, "ShellTask");
609     if (ret != SH_OK) {
610         return NULL;
611     }
612 
613     printf(SHELL_PROMPT);
614     while (1) {
615         ret = ShellPend(shellCB);
616         if (ret == SH_OK) {
617             ShellCmdProcess(shellCB);
618         } else if (ret != SH_OK) {
619             break;
620         }
621     }
622 
623     return NULL;
624 }
625 
ShellTaskInit(ShellCB * shellCB)626 int ShellTaskInit(ShellCB *shellCB)
627 {
628     unsigned int ret;
629     size_t stackSize = SHELL_TASK_STACKSIZE;
630     void *arg = NULL;
631     pthread_attr_t attr;
632 
633     if (shellCB == NULL) {
634         return SH_NOK;
635     }
636 
637     ret = pthread_attr_init(&attr);
638     if (ret != SH_OK) {
639         return SH_NOK;
640     }
641 
642     pthread_attr_setstacksize(&attr, stackSize);
643     arg = (void *)shellCB;
644     ret = pthread_create(&shellCB->shellTaskHandle, &attr, &ShellTask, arg);
645     if (ret != SH_OK) {
646         return SH_NOK;
647     }
648 
649     return ret;
650 }
651 
ShellKernelReg(unsigned int shellHandle)652 static int ShellKernelReg(unsigned int shellHandle)
653 {
654     return ioctl(STDIN_FILENO, CONSOLE_CONTROL_REG_USERTASK, shellHandle);
655 }
656 
ShellEntry(void * argv)657 void *ShellEntry(void *argv)
658 {
659     char ch;
660     int ret;
661     int n;
662     pid_t tid = syscall(__NR_gettid);
663     ShellCB *shellCB = (ShellCB *)argv;
664 
665     if (shellCB == NULL) {
666         return NULL;
667     }
668 
669     (void)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);
670 
671     ret = prctl(PR_SET_NAME, "ShellEntry");
672     if (ret != SH_OK) {
673         return NULL;
674     }
675 
676     ret = ShellKernelReg((int)tid);
677     if (ret != 0) {
678         printf("another shell is already running!\n");
679         exit(-1);
680     }
681 
682     while (1) {
683         n = read(0, &ch, 1);
684         if (n == 1) {
685             ShellCmdLineParse(ch, (OutputFunc)printf, shellCB);
686         }
687     }
688     return NULL;
689 }
690 
ShellEntryInit(ShellCB * shellCB)691 int ShellEntryInit(ShellCB *shellCB)
692 {
693     int ret;
694     size_t stackSize = SHELL_ENTRY_STACKSIZE;
695     void *arg = NULL;
696     pthread_attr_t attr;
697 
698     if (shellCB == NULL) {
699         return SH_NOK;
700     }
701 
702     ret = pthread_attr_init(&attr);
703     if (ret != SH_OK) {
704         return SH_NOK;
705     }
706 
707     pthread_attr_setstacksize(&attr, stackSize);
708     arg = (void *)shellCB;
709     ret = pthread_create(&shellCB->shellEntryHandle, &attr, &ShellEntry, arg);
710     if (ret != SH_OK) {
711         return SH_NOK;
712     }
713 
714     return ret;
715 }
716 
717