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