• 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[],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