feat: add L0 shell function

Change-Id: I7f10bd365455c32006c22a9f6e2368fe6c229a6a
Signed-off-by: silen <wuyunjie@huawei.com>
This commit is contained in:
silen
2021-07-11 20:04:00 +08:00
parent bf045e3eba
commit 97283b7c5d
21 changed files with 3667 additions and 14 deletions

454
components/shell/src/base/shcmd.c Executable file
View File

@@ -0,0 +1,454 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shcmd.h"
#include "show.h"
#include "shmsg.h"
#include "stdlib.h"
#include "unistd.h"
#include "dirent.h"
#include "securec.h"
#include "los_mux.h"
#include "los_memory.h"
#include "los_typedef.h"
#define SHELL_INIT_MAGIC_FLAG 0xABABABAB
STATIC CmdModInfo cmdInfo;
ShellCB *g_shellCB = NULL;
CmdItem g_shellcmdAll[] = {
{CMD_TYPE_STD, "date", XARGS, (CmdCallBackFunc)OsShellCmdDate},
{CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask},
{CMD_TYPE_EX, "free", XARGS, (CmdCallBackFunc)OsShellCmdFree},
{CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig},
{CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)OsShellPing},
{CMD_TYPE_EX, "touch", XARGS, (CmdCallBackFunc)OsShellCmdTouch},
{CMD_TYPE_EX, "ls", XARGS, (CmdCallBackFunc)OsShellCmdLs},
{CMD_TYPE_EX, "pwd", XARGS, (CmdCallBackFunc)OsShellCmdPwd},
{CMD_TYPE_EX, "cd", XARGS, (CmdCallBackFunc)OsShellCmdCd},
{CMD_TYPE_EX, "cat", XARGS, (CmdCallBackFunc)OsShellCmdCat},
{CMD_TYPE_EX, "rm", XARGS, (CmdCallBackFunc)OsShellCmdRm},
{CMD_TYPE_EX, "rmdir", XARGS, (CmdCallBackFunc)OsShellCmdRmdir},
{CMD_TYPE_EX, "mkdir", XARGS, (CmdCallBackFunc)OsShellCmdMkdir},
{CMD_TYPE_EX, "cp", XARGS, (CmdCallBackFunc)OsShellCmdCp},
{CMD_TYPE_EX, "help", 0, (CmdCallBackFunc)OsShellCmdHelp},
};
CmdModInfo *OsCmdInfoGet(VOID)
{
return &cmdInfo;
}
/*
* Description: Pass in the string and clear useless space ,which inlcude:
* 1) The overmatch space which is not be marked by Quote's area
* Squeeze the overmatch space into one space
* 2) Clear all space before first vaild charatctor
* Input: cmdKey : Pass in the buff string, which is ready to be operated
* cmdOut : Pass out the buffer string ,which has already been operated
* size : cmdKey length
*/
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdKeyShift(const CHAR *cmdKey, CHAR *cmdOut, UINT32 size)
{
CHAR *output = NULL;
CHAR *outputBak = NULL;
UINT32 len;
INT32 ret;
BOOL quotes = FALSE;
if ((cmdKey == NULL) || (cmdOut == NULL)) {
return (UINT32)OS_ERROR;
}
len = strlen(cmdKey);
if (len >= size) {
return (UINT32)OS_ERROR;
}
output = (CHAR*)LOS_MemAlloc(m_aucSysMem0, len + 1);
if (output == NULL) {
PRINTK("malloc failure in %s[%d]", __FUNCTION__, __LINE__);
return (UINT32)OS_ERROR;
}
/* Backup the 'output' start address */
outputBak = output;
/* Scan each charactor in 'cmdKey',and squeeze the overmuch space and ignore invaild charactor */
for (; *cmdKey != '\0'; cmdKey++) {
/* Detected a Double Quotes, switch the matching status */
if (*(cmdKey) == '\"') {
SWITCH_QUOTES_STATUS(quotes);
}
/* Ignore the current charactor in following situation */
/* 1) Quotes matching status is FALSE (which said that the space is not been marked by double quotes) */
/* 2) Current charactor is a space */
/* 3) Next charactor is a space too, or the string is been seeked to the end already(\0) */
/* 4) Invaild charactor, such as single quotes */
if ((*cmdKey == ' ') && ((*(cmdKey + 1) == ' ') || (*(cmdKey + 1) == '\0')) && QUOTES_STATUS_CLOSE(quotes)) {
continue;
}
if (*cmdKey == '\'') {
continue;
}
*output = *cmdKey;
output++;
}
*output = '\0';
/* Restore the 'output' start address */
output = outputBak;
len = strlen(output);
/* Clear the space which is located at the first charactor in buffer */
if (*outputBak == ' ') {
output++;
len--;
}
/* Copy out the buffer which is been operated already */
ret = strncpy_s(cmdOut, size, output, len);
if (ret != EOK) {
PRINT_ERR("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret);
(VOID)LOS_MemFree(m_aucSysMem0, output);
return OS_ERROR;
}
cmdOut[len] = '\0';
(VOID)LOS_MemFree(m_aucSysMem0, output);
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey)
{
const CHAR *temp = cmdKey;
enum Stat {
STAT_NONE,
STAT_DIGIT,
STAT_OTHER
} state = STAT_NONE;
if (strlen(cmdKey) >= CMD_KEY_LEN) {
return FALSE;
}
while (*temp != '\0') {
if (!((*temp <= '9') && (*temp >= '0')) &&
!((*temp <= 'z') && (*temp >= 'a')) &&
!((*temp <= 'Z') && (*temp >= 'A')) &&
(*temp != '_') && (*temp != '-')) {
return FALSE;
}
if ((*temp >= '0') && (*temp <= '9')) {
if (state == STAT_NONE) {
state = STAT_DIGIT;
}
} else {
state = STAT_OTHER;
}
temp++;
}
if (state == STAT_DIGIT) {
return FALSE;
}
return TRUE;
}
LITE_OS_SEC_TEXT_MINOR VOID OsCmdAscendingInsert(CmdItemNode *cmd)
{
CmdItemNode *cmdItem = NULL;
CmdItemNode *cmdNext = NULL;
if (cmd == NULL) {
return;
}
for (cmdItem = LOS_DL_LIST_ENTRY((&cmdInfo.cmdList.list)->pstPrev, CmdItemNode, list);
&cmdItem->list != &(cmdInfo.cmdList.list);) {
cmdNext = LOS_DL_LIST_ENTRY(cmdItem->list.pstPrev, CmdItemNode, list);
if (&cmdNext->list != &(cmdInfo.cmdList.list)) {
if ((strncmp(cmdItem->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) >= 0) &&
(strncmp(cmdNext->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) < 0)) {
LOS_ListTailInsert(&(cmdItem->list), &(cmd->list));
return;
}
cmdItem = cmdNext;
} else {
if (strncmp(cmd->cmd->cmdKey, cmdItem->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) > 0) {
cmdItem = cmdNext;
}
break;
}
}
LOS_ListTailInsert(&(cmdItem->list), &(cmd->list));
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellKeyInit(ShellCB *shellCB)
{
CmdKeyLink *cmdKeyLink = NULL;
CmdKeyLink *cmdHistoryLink = NULL;
if (shellCB == NULL) {
return OS_ERROR;
}
cmdKeyLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink));
if (cmdKeyLink == NULL) {
PRINT_ERR("Shell CmdKeyLink memory alloc error!\n");
return OS_ERROR;
}
cmdHistoryLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink));
if (cmdHistoryLink == NULL) {
(VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink);
PRINT_ERR("Shell CmdHistoryLink memory alloc error!\n");
return OS_ERROR;
}
cmdKeyLink->count = 0;
LOS_ListInit(&(cmdKeyLink->list));
shellCB->cmdKeyLink = (VOID *)cmdKeyLink;
cmdHistoryLink->count = 0;
LOS_ListInit(&(cmdHistoryLink->list));
shellCB->cmdHistoryKeyLink = (VOID *)cmdHistoryLink;
shellCB->cmdMaskKeyLink = (VOID *)cmdHistoryLink;
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellKeyDeInit(CmdKeyLink *cmdKeyLink)
{
CmdKeyLink *cmdtmp = NULL;
if (cmdKeyLink == NULL) {
return;
}
while (!LOS_ListEmpty(&(cmdKeyLink->list))) {
cmdtmp = LOS_DL_LIST_ENTRY(cmdKeyLink->list.pstNext, CmdKeyLink, list);
LOS_ListDelete(&cmdtmp->list);
(VOID)LOS_MemFree(m_aucSysMem0, cmdtmp);
}
cmdKeyLink->count = 0;
(VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink);
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellSysCmdRegister(VOID)
{
UINT32 i;
UINT8 *cmdItemGroup = NULL;
UINT32 index = sizeof(g_shellcmdAll) / sizeof(CmdItem);
CmdItemNode *cmdItem = NULL;
cmdItemGroup = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, index * sizeof(CmdItemNode));
if (cmdItemGroup == NULL) {
PRINT_ERR("[%s]System memory allocation failure!\n", __FUNCTION__);
return (UINT32)OS_ERROR;
}
for (i = 0; i < index; ++i) {
cmdItem = (CmdItemNode *)(cmdItemGroup + i * sizeof(CmdItemNode));
cmdItem->cmd = &g_shellcmdAll[i];
OsCmdAscendingInsert(cmdItem);
}
cmdInfo.listNum += index;
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr)
{
UINT32 ret;
CmdCallBackFunc cmdHook = NULL;
CmdItemNode *curCmdItem = NULL;
UINT32 i;
const CHAR *cmdKey = NULL;
if ((cmdParsed == NULL) || (cmdStr == NULL) || (strlen(cmdStr) == 0)) {
return (UINT32)OS_ERROR;
}
ret = OsCmdParse(cmdStr, cmdParsed);
if (ret != LOS_OK) {
goto OUT;
}
LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo.cmdList.list), CmdItemNode, list) {
cmdKey = curCmdItem->cmd->cmdKey;
if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) &&
(strlen(cmdKey) == strlen(cmdParsed->cmdKeyword)) &&
(strncmp(cmdKey, (CHAR *)(cmdParsed->cmdKeyword), strlen(cmdKey)) == 0)) {
cmdHook = curCmdItem->cmd->cmdHook;
break;
}
}
ret = OS_ERROR;
if (cmdHook != NULL) {
ret = (cmdHook)(cmdParsed->paramCnt, (const CHAR **)cmdParsed->paramArray);
}
OUT:
for (i = 0; i < cmdParsed->paramCnt; i++) {
if (cmdParsed->paramArray[i] != NULL) {
(VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]);
cmdParsed->paramArray[i] = NULL;
}
}
return (UINT32)ret;
}
ShellCB *OsGetShellCb(VOID)
{
return g_shellCB;
}
char *OsShellGetWorkingDirtectory(VOID)
{
return OsGetShellCb()->shellWorkingDirectory;
}
VOID OsShellCBInit(VOID)
{
int ret;
ShellCB *shellCB = NULL;
shellCB = (ShellCB *)malloc(sizeof(ShellCB));
if (shellCB == NULL) {
goto ERR_OUT1;
}
ret = memset_s(shellCB, sizeof(ShellCB), 0, sizeof(ShellCB));
if (ret != SH_OK) {
goto ERR_OUT1;
}
ret = (int)OsShellKeyInit(shellCB);
if (ret != SH_OK) {
goto ERR_OUT1;
}
(void)strncpy_s(shellCB->shellWorkingDirectory, PATH_MAX, "/", 2); /* 2:space for "/" */
g_shellCB = shellCB;
return;
ERR_OUT1:
(void)free(shellCB);
return;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdInit(VOID)
{
UINT32 ret;
LOS_ListInit(&(cmdInfo.cmdList.list));
cmdInfo.listNum = 0;
cmdInfo.initMagicFlag = SHELL_INIT_MAGIC_FLAG;
ret = LOS_MuxCreate(&cmdInfo.muxLock);
if (ret != LOS_OK) {
PRINT_ERR("Create mutex for shell cmd info failed\n");
return OS_ERROR;
}
OsShellCBInit();
return LOS_OK;
}
STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
{
CmdItem *cmdItem = NULL;
CmdItemNode *cmdItemNode = NULL;
cmdItem = (CmdItem *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItem));
if (cmdItem == NULL) {
return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
}
(VOID)memset_s(cmdItem, sizeof(CmdItem), '\0', sizeof(CmdItem));
cmdItemNode = (CmdItemNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItemNode));
if (cmdItemNode == NULL) {
(VOID)LOS_MemFree(m_aucSysMem0, cmdItem);
return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
}
(VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode));
cmdItemNode->cmd = cmdItem;
cmdItemNode->cmd->cmdHook = cmdProc;
cmdItemNode->cmd->paraNum = paraNum;
cmdItemNode->cmd->cmdType = cmdType;
cmdItemNode->cmd->cmdKey = cmdKey;
(VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER);
OsCmdAscendingInsert(cmdItemNode);
cmdInfo.listNum++;
(VOID)LOS_MuxPost(cmdInfo.muxLock);
return LOS_OK;
}
/* open API */
LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
{
CmdItemNode *cmdItemNode = NULL;
(VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER);
if (cmdInfo.initMagicFlag != SHELL_INIT_MAGIC_FLAG) {
(VOID)LOS_MuxPost(cmdInfo.muxLock);
PRINT_ERR("[%s] shell is not yet initialized!\n", __FUNCTION__);
return OS_ERRNO_SHELL_NOT_INIT;
}
(VOID)LOS_MuxPost(cmdInfo.muxLock);
if ((cmdProc == NULL) || (cmdKey == NULL) ||
(cmdType >= CMD_TYPE_BUTT) || (strlen(cmdKey) >= CMD_KEY_LEN) || !strlen(cmdKey)) {
return OS_ERRNO_SHELL_CMDREG_PARA_ERROR;
}
if (paraNum > CMD_MAX_PARAS) {
if (paraNum != XARGS) {
return OS_ERRNO_SHELL_CMDREG_PARA_ERROR;
}
}
if (OsCmdKeyCheck(cmdKey) != TRUE) {
return OS_ERRNO_SHELL_CMDREG_CMD_ERROR;
}
(VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER);
LOS_DL_LIST_FOR_EACH_ENTRY(cmdItemNode, &(cmdInfo.cmdList.list), CmdItemNode, list) {
if ((cmdType == cmdItemNode->cmd->cmdType) &&
((strlen(cmdKey) == strlen(cmdItemNode->cmd->cmdKey)) &&
(strncmp((CHAR *)(cmdItemNode->cmd->cmdKey), cmdKey, strlen(cmdKey)) == 0))) {
(VOID)LOS_MuxPost(cmdInfo.muxLock);
return OS_ERRNO_SHELL_CMDREG_CMD_EXIST;
}
}
(VOID)LOS_MuxPost(cmdInfo.muxLock);
return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc);
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shcmd.h"
#include "los_memory.h"
/*
* Filter out double quote or single-quoted strings at both ends
*/
LITE_OS_SEC_TEXT_MINOR CHAR *OsCmdParseStrdup(const CHAR *str)
{
CHAR *tempStr = NULL;
CHAR *newStr = NULL;
newStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, strlen(str) + 1);
if (newStr == NULL) {
return NULL;
}
tempStr = newStr;
for (; *str != '\0'; str++) {
if ((*str == '\"') || (*str == '\'')) {
continue;
}
*newStr = *str;
newStr++;
}
*newStr = '\0';
return tempStr;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseParaGet(CHAR **value, const CHAR *paraTokenStr)
{
if ((paraTokenStr == NULL) || (value == NULL)) {
return (UINT32)OS_ERROR;
}
*value = OsCmdParseStrdup(paraTokenStr);
if (*value == NULL) {
return LOS_NOK;
}
return LOS_OK;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 index, const CHAR *token)
{
UINT32 ret = LOS_OK;
UINT32 tempLen;
if (cmdParsed == NULL) {
return (UINT32)OS_ERROR;
}
if (index == 0) {
if (cmdParsed->cmdType != CMD_TYPE_STD) {
return ret;
}
}
if ((token != NULL) && (cmdParsed->paramCnt < CMD_MAX_PARAS)) {
tempLen = cmdParsed->paramCnt;
ret = OsCmdParseParaGet(&(cmdParsed->paramArray[tempLen]), token);
if (ret != LOS_OK) {
return ret;
}
cmdParsed->paramCnt++;
}
return ret;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParsed *cmdParsed)
{
enum {
STAT_INIT,
STAT_TOKEN_IN,
STAT_TOKEN_OUT
} state = STAT_INIT;
UINT32 count = 0;
CHAR *p = NULL;
CHAR *token = cmdStr;
UINT32 ret = LOS_OK;
BOOL quotes = FALSE;
if (cmdStr == NULL) {
return (UINT32)OS_ERROR;
}
for (p = cmdStr; (*p != '\0') && (ret == LOS_OK); p++) {
if (*p == '\"') {
SWITCH_QUOTES_STATUS(quotes);
}
switch (state) {
case STAT_INIT:
case STAT_TOKEN_IN:
if ((*p == split) && QUOTES_STATUS_CLOSE(quotes)) {
*p = '\0';
ret = OsCmdParseOneToken(cmdParsed, count++, token);
state = STAT_TOKEN_OUT;
}
break;
case STAT_TOKEN_OUT:
if (*p != split) {
token = p;
state = STAT_TOKEN_IN;
}
break;
default:
break;
}
}
if (((ret == LOS_OK) && (state == STAT_TOKEN_IN)) || (state == STAT_INIT)) {
ret = OsCmdParseOneToken(cmdParsed, count, token);
}
return ret;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParse(CHAR *cmdStr, CmdParsed *cmdParsed)
{
if ((cmdStr == NULL) || (cmdParsed == NULL) || (strlen(cmdStr) == 0)) {
return (UINT32)OS_ERROR;
}
return OsCmdTokenSplit(cmdStr, ' ', cmdParsed);
}

223
components/shell/src/base/shmsg.c Executable file
View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shmsg.h"
#include "shcmd.h"
#include "show.h"
#include "securec.h"
UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType)
{
CmdItemNode *curCmdItem = (CmdItemNode *)NULL;
UINT32 len;
UINT32 minLen;
CmdModInfo *cmdInfo = OsCmdInfoGet();
if ((cmdParsed == NULL) || (cmdType == NULL)) {
return OS_INVALID;
}
len = strlen(cmdType);
LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) {
if ((len == strlen(curCmdItem->cmd->cmdKey)) &&
(strncmp((CHAR *)(curCmdItem->cmd->cmdKey), cmdType, len) == 0)) {
minLen = (len < CMD_KEY_LEN) ? len : CMD_KEY_LEN;
(VOID)memcpy_s((CHAR *)(cmdParsed->cmdKeyword), CMD_KEY_LEN, cmdType, minLen);
cmdParsed->cmdType = curCmdItem->cmd->cmdType;
return LOS_OK;
}
}
return OS_INVALID;
}
char *GetCmdName(const char *cmdline, unsigned int len)
{
unsigned int loop;
const char *tmpStr = NULL;
bool quotes = FALSE;
char *cmdName = NULL;
if (cmdline == NULL) {
return NULL;
}
cmdName = (char *)malloc(len + 1);
if (cmdName == NULL) {
PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
return NULL;
}
/* Scan the 'cmdline' string for command */
/* Notice: Command string must not have any special name */
for (tmpStr = cmdline, loop = 0; (*tmpStr != '\0') && (loop < len);) {
/* If reach a double quotes, switch the quotes matching status */
if (*tmpStr == '\"') {
SWITCH_QUOTES_STATUS(quotes);
/* Ignore the double quote charactor itself */
tmpStr++;
continue;
}
/* If detected a space which the quotes matching status is false */
/* which said has detected the first space for seperator, finish this scan operation */
if ((*tmpStr == ' ') && (QUOTES_STATUS_CLOSE(quotes))) {
break;
}
cmdName[loop] = *tmpStr++;
loop++;
}
cmdName[loop] = '\0';
return cmdName;
}
int ShellCmdExec(const char *msgName, const char *cmdString)
{
unsigned int uintRet;
errno_t err;
CmdParsed cmdParsed;
if (msgName == NULL || cmdString == NULL) {
return -EFAULT;
}
err = memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed));
if (err != EOK) {
return -EFAULT;
}
uintRet = ShellMsgTypeGet(&cmdParsed, msgName);
if (uintRet != LOS_OK) {
PRINTK("%s:command not found\n", msgName);
return -EFAULT;
} else {
(void)OsCmdExec(&cmdParsed, (char *)cmdString);
}
return 0;
}
unsigned int PreHandleCmdline(const char *input, char **output, unsigned int *outputlen)
{
unsigned int shiftLen;
unsigned int ret;
const char *cmdBuf = input;
unsigned int cmdBufLen = strlen(cmdBuf);
char *shiftStr = (char *)malloc(cmdBufLen + 1);
if (shiftStr == NULL) {
PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
return SH_NOK;
}
(void)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1);
/* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */
ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1);
shiftLen = strlen(shiftStr);
if ((ret != SH_OK) || (shiftLen == 0)) {
ret = SH_NOK;
goto END_FREE_SHIFTSTR;
}
*output = shiftStr;
*outputlen = shiftLen;
ret = SH_OK;
goto END;
END_FREE_SHIFTSTR:
free(shiftStr);
END:
return ret;
}
static void ParseAndExecCmdline(CmdParsed *cmdParsed, const char *cmdline, unsigned int len)
{
int i;
unsigned int ret;
char *cmdlineOrigin = NULL;
char *cmdName = NULL;
cmdlineOrigin = strdup(cmdline);
if (cmdlineOrigin == NULL) {
PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
return;
}
cmdName = GetCmdName(cmdline, len);
if (cmdName == NULL) {
free(cmdlineOrigin);
PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__);
return;
}
ret = OsCmdParse((char *)cmdline, cmdParsed);
if (ret != SH_OK) {
PRINTK("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__);
goto OUT;
}
(void)ShellCmdExec(cmdName, cmdlineOrigin);
OUT:
for (i = 0; i < cmdParsed->paramCnt; i++) {
if (cmdParsed->paramArray[i] != NULL) {
free(cmdParsed->paramArray[i]);
cmdParsed->paramArray[i] = NULL;
}
}
free(cmdName);
free(cmdlineOrigin);
}
LITE_OS_SEC_TEXT_MINOR void ExecCmdline(const char *cmdline)
{
unsigned int ret;
char *output = NULL;
unsigned int outputlen;
CmdParsed cmdParsed;
if (cmdline == NULL) {
return;
}
OsShellInit(0);
/* strip out unnecessary characters */
ret = PreHandleCmdline(cmdline, &output, &outputlen);
if (ret == SH_NOK) {
return;
}
(void)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed));
ParseAndExecCmdline(&cmdParsed, output, outputlen);
free(output);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "show.h"
#include "shmsg.h"
#include "shcmd.h"
STATIC BOOL g_shellSourceFlag = FALSE;
STATIC UINT32 OsShellCmdInit(VOID)
{
UINT32 ret = OsCmdInit();
if (ret != LOS_OK) {
return ret;
}
return OsShellSysCmdRegister();
}
UINT32 OsShellInit(INT32 consoleId)
{
if (g_shellSourceFlag == FALSE) {
UINT32 ret = OsShellCmdInit();
if (ret == LOS_OK) {
g_shellSourceFlag = TRUE;
} else {
return ret;
}
}
return 0;
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shcmd.h"
#include "shell.h"
#include "stdlib.h"
#include "sys/time.h"
#include "los_typedef.h"
#include "sys/stat.h"
#include "securec.h"
#define DATE_ERR (-1)
#define DATE_OK 0
INT32 OsShellCmdDate(INT32 argc, const CHAR **argv)
{
struct timeval nowTime;
if (argc == 1) { /* 1:count of parameters */
if (gettimeofday(&nowTime, NULL)) {
return DATE_ERR;
}
PRINTK("%s\n", ctime(&nowTime.tv_sec));
return DATE_OK;
}
return DATE_OK;
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "errno.h"
#include "limits.h"
#include "shell.h"
#include "show.h"
#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
static unsigned int VfsStrnlen(const char *str, size_t maxlen)
{
const char *p = NULL;
for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {}
return p - str;
}
/* abandon the redundant '/' in the path, only keep one. */
static char *StrPath(char *path)
{
char *dest = path;
char *src = path;
while (*src != '\0') {
if (*src == '/') {
*dest++ = *src++;
while (*src == '/') {
src++;
}
continue;
}
*dest++ = *src++;
}
*dest = '\0';
return path;
}
static void StrRemovePathEndSlash(char *dest, const char *fullpath)
{
if ((*dest == '.') && (*(dest - 1) == '/')) {
*dest = '\0';
dest--;
}
if ((dest != fullpath) && (*dest == '/')) {
*dest = '\0';
}
}
static char *StrNormalizePath(char *fullpath)
{
char *dest = fullpath;
char *src = fullpath;
/* 2: The position of the path character: / and the end character /0 */
while (*src != '\0') {
if (*src == '.') {
if (*(src + 1) == '/') {
src += 2;
continue;
} else if (*(src + 1) == '.') {
if ((*(src + 2) == '/') || (*(src + 2) == '\0')) {
src += 2;
} else {
while ((*src != '\0') && (*src != '/')) {
*dest++ = *src++;
}
continue;
}
} else {
*dest++ = *src++;
continue;
}
} else {
*dest++ = *src++;
continue;
}
if ((dest - 1) != fullpath) {
dest--;
}
while ((dest > fullpath) && (*(dest - 1) != '/')) {
dest--;
}
if (*src == '/') {
src++;
}
}
*dest = '\0';
/* remove '/' in the end of path if exist */
dest--;
StrRemovePathEndSlash(dest, fullpath);
return dest;
}
static int VfsNormalizePathParameCheck(const char *filename, char **pathname)
{
int namelen;
char *name = NULL;
if (pathname == NULL) {
return -EINVAL;
}
/* check parameters */
if (filename == NULL) {
*pathname = NULL;
return -EINVAL;
}
namelen = VfsStrnlen(filename, PATH_MAX);
if (!namelen) {
*pathname = NULL;
return -EINVAL;
} else if (namelen >= PATH_MAX) {
*pathname = NULL;
return -ENAMETOOLONG;
}
for (name = (char *)filename + namelen; ((name != filename) && (*name != '/')); name--) {
if (strlen(name) > NAME_MAX) {
*pathname = NULL;
return -ENAMETOOLONG;
}
}
return namelen;
}
static char *VfsNotAbsolutePath(const char *directory, const char *filename, char **pathname, int namelen)
{
int ret;
char *fullpath = NULL;
/* 2: The position of the path character: / and the end character /0 */
if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) {
filename += 2;
}
fullpath = (char *)malloc(strlen(directory) + namelen + 2);
if (fullpath == NULL) {
*pathname = NULL;
SetErrno(ENOMEM);
return (char *)NULL;
}
/* join path and file name */
ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1,
"%s/%s", directory, filename);
if (ret < 0) {
*pathname = NULL;
free(fullpath);
SetErrno(ENAMETOOLONG);
return (char *)NULL;
}
return fullpath;
}
static char *VfsNormalizeFullpath(const char *directory, const char *filename, char **pathname, int namelen)
{
char *fullpath = NULL;
if (filename[0] != '/') {
/* not a absolute path */
fullpath = VfsNotAbsolutePath(directory, filename, pathname, namelen);
if (fullpath == NULL) {
return (char *)NULL;
}
} else {
/* it's a absolute path, use it directly */
fullpath = strdup(filename); /* copy string */
if (fullpath == NULL) {
*pathname = NULL;
SetErrno(ENOMEM);
return (char *)NULL;
}
if (filename[1] == '/') {
*pathname = NULL;
free(fullpath);
SetErrno(EINVAL);
return (char *)NULL;
}
}
return fullpath;
}
int VfsNormalizePath(const char *directory, const char *filename, char **pathname)
{
char *fullpath = NULL;
int namelen;
namelen = VfsNormalizePathParameCheck(filename, pathname);
if (namelen < 0) {
return namelen;
}
if ((directory == NULL) && (filename[0] != '/')) {
PRINT_ERR("NO_WORKING_DIR\n");
*pathname = NULL;
return -EINVAL;
}
/* 2: The position of the path character: / and the end character /0 */
if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) {
return -ENAMETOOLONG;
}
fullpath = VfsNormalizeFullpath(directory, filename, pathname, namelen);
if (fullpath == NULL) {
return -errno;
}
(void)StrPath(fullpath);
(void)StrNormalizePath(fullpath);
if (strlen(fullpath) >= PATH_MAX) {
*pathname = NULL;
free(fullpath);
return -ENAMETOOLONG;
}
*pathname = fullpath;
return ENOERR;
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "stdlib.h"
#include "shcmd.h"
#include "shell.h"
#define MEM_SIZE_1K 0x400
#define MEM_SIZE_1M 0x100000
#define MEM_SIZE_TO_KB(size) (((size) + (MEM_SIZE_1K >> 1)) / MEM_SIZE_1K)
#define MEM_SIZE_TO_MB(size) (((size) + (MEM_SIZE_1M >> 1)) / MEM_SIZE_1M)
LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OsShellCmdFreeInfo(INT32 argc, const CHAR *argv[])
{
UINT32 memUsed = LOS_MemTotalUsedGet(m_aucSysMem0);
UINT32 totalMem = LOS_MemPoolSizeGet(m_aucSysMem0);
UINT32 freeMem = totalMem - memUsed;
if ((argc == 0) ||
((argc == 1) && (strcmp(argv[0], "-k") == 0)) ||
((argc == 1) && (strcmp(argv[0], "-m") == 0))) {
PRINTK("\r\n total used free\n");
}
if ((argc == 1) && (strcmp(argv[0], "-k") == 0)) {
PRINTK("Mem: %-9u %-10u %-10u\n", MEM_SIZE_TO_KB(totalMem), MEM_SIZE_TO_KB(memUsed),
MEM_SIZE_TO_KB(freeMem));
} else if ((argc == 1) && (strcmp(argv[0], "-m") == 0)) {
PRINTK("Mem: %-9u %-10u %-10u\n", MEM_SIZE_TO_MB(totalMem), MEM_SIZE_TO_MB(memUsed),
MEM_SIZE_TO_MB(freeMem));
} else if (argc == 0) {
PRINTK("Mem: %-9u %-10u %-10u\n", totalMem, memUsed, freeMem);
} else {
PRINTK("\nUsage: free or free [-k/-m]\n");
return OS_ERROR;
}
return 0;
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdFree(INT32 argc, const CHAR *argv[])
{
if (argc > 1) {
PRINTK("\nUsage: free or free [-k/-m]\n");
return OS_ERROR;
}
if (OsShellCmdFreeInfo(argc, argv) != 0) {
return OS_ERROR;
}
return 0;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "shcmd.h"
INT32 OsShellCmdHelp(INT32 argc, const CHAR **argv)
{
UINT32 loop = 0;
CmdItemNode *curCmdItem = NULL;
CmdModInfo *cmdInfo = OsCmdInfoGet();
(VOID)argv;
if (argc > 0) {
PRINTK("\nUsage: help\n");
return OS_ERROR;
}
PRINTK("*******************shell commands:*************************\n");
LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) {
if ((loop & (8 - 1)) == 0) { /* 8 - 1:just align print */
PRINTK("\n");
}
PRINTK("%-12s ", curCmdItem->cmd->cmdKey);
loop++;
}
PRINTK("\n");
return 0;
}

View File

@@ -0,0 +1,123 @@
#include "stdlib.h"
#include "los_config.h"
#include "los_exc.h"
#include "los_task.h"
#include "los_sem.h"
#include "shcmd.h"
#include "shell.h"
#define OS_INVALID_SEM_ID 0xFFFFFFFF
LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdConvertTskStatus(UINT16 taskStatus)
{
if (taskStatus & OS_TASK_STATUS_RUNNING) {
return (UINT8 *)"Running";
} else if (taskStatus & OS_TASK_STATUS_READY) {
return (UINT8 *)"Ready";
} else {
if (taskStatus & OS_TASK_STATUS_DELAY) {
return (UINT8 *)"Delay";
} else if (taskStatus & OS_TASK_STATUS_PEND_QUEUE) {
return (UINT8 *)"Pend";
} else if (taskStatus & OS_TASK_STATUS_PEND) {
return (UINT8 *)"Pend";
} else if (taskStatus & OS_TASK_STATUS_SUSPEND) {
return (UINT8 *)"Suspend";
}
}
return (UINT8 *)"Invalid";
}
LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitle(VOID)
{
PRINTK("\r\nName TaskEntryAddr TID ");
PRINTK("Priority Status "
"StackSize StackPoint TopOfStack");
PRINTK("\n");
PRINTK("---- ------------- --- ");
PRINTK("-------- -------- "
"--------- ---------- ----------");
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsGetSemID(const LosTaskCB *taskCB)
{
UINT32 semId = OS_INVALID_SEM_ID;
if (taskCB->taskSem != NULL) {
semId = ((LosSemCB *)taskCB->taskSem)->semID;
}
return semId;
}
LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoData(const LosTaskCB *allTaskArray)
{
const LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 semId;
for (loop = 0; loop < g_taskMaxNum; ++loop) {
taskCB = allTaskArray + loop;
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
continue;
}
semId = OsGetSemID(taskCB);
PRINTK("%-23s%-20p0x%-5x", taskCB->taskName, taskCB->taskEntry, taskCB->taskID);
PRINTK("%-11u%-13s0x%-11x 0x%-8x 0x%-10x ", taskCB->priority,
OsShellCmdConvertTskStatus(taskCB->taskStatus), taskCB->stackSize,
taskCB->stackPointer, taskCB->topOfStack, semId);
PRINTK("\n");
}
}
LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskId)
{
BOOL backupFlag = TRUE;
UINT32 size;
LosTaskCB *tcbArray = NULL;
INT32 ret;
if (taskId == OS_ALL_TASK_MASK) {
size = g_taskMaxNum * sizeof(LosTaskCB);
tcbArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
if (tcbArray == NULL) {
PRINTK("Memory is not enough to save task info!\n");
tcbArray = g_taskCBArray;
backupFlag = FALSE;
}
if (backupFlag == TRUE) {
ret = memcpy_s(tcbArray, size, g_taskCBArray, size);
if (ret != 0) {
return LOS_NOK;
}
}
OsShellCmdTskInfoTitle();
OsShellCmdTskInfoData(tcbArray);
if (backupFlag == TRUE) {
(VOID)LOS_MemFree(m_aucSysMem0, tcbArray);
}
}
return LOS_OK;
}
INT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv)
{
size_t taskId = OS_ALL_TASK_MASK;
if (argc < 1) {
return OsShellCmdTskInfoGet((UINT32)taskId);
} else {
PRINTK("\nUsage: task\n");
return OS_ERROR;
}
}

View File

@@ -0,0 +1,956 @@
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_config.h"
#include "sys/mount.h"
#include "los_task.h"
#include "los_typedef.h"
#include "shell.h"
#include "sys/stat.h"
#include "stdlib.h"
#include "unistd.h"
#include "fcntl.h"
#include "sys/statfs.h"
#include "stdio.h"
#include "pthread.h"
#include "shcmd.h"
#include "securec.h"
#include "show.h"
#include <dirent.h>
#include <ctype.h>
#define VFS_ERROR OS_ERROR
#define SHOW_MAX_LEN CMD_MAX_LEN
#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
typedef enum {
RM_RECURSIVER,
RM_FILE,
RM_DIR,
CP_FILE,
CP_COUNT
} wildcard_type;
#define ERROR_OUT_IF(condition, message_function, handler) \
do { \
if (condition) { \
message_function; \
handler; \
} \
} while (0)
int OsShellCmdDoChdir(const char *path)
{
char *fullpath = NULL;
char *fullpathBak = NULL;
DIR *dirent = NULL;
int ret;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
if (path == NULL) {
LOS_TaskLock();
PRINTK("%s\n", shellWorkingDirectory);
LOS_TaskUnlock();
return 0;
}
ERROR_OUT_IF(strlen(path) > PATH_MAX, SetErr(ENOTDIR, "cd error"), return -1);
ret = VfsNormalizePath(shellWorkingDirectory, path, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "cd error"), return -1);
fullpathBak = fullpath;
dirent = opendir(fullpath);
if (dirent == NULL) {
free(fullpathBak);
/* this is a not exist directory */
PRINTK("no such file or directory\n");
return -1;
}
/* close directory stream */
(void)closedir(dirent);
/* copy full path to working directory */
LOS_TaskLock();
ret = strncpy_s(shellWorkingDirectory, PATH_MAX, fullpath, strlen(fullpath));
if (ret != EOK) {
free(fullpathBak);
LOS_TaskUnlock();
return -1;
}
LOS_TaskUnlock();
/* release normalize directory path name */
free(fullpathBak);
return 0;
}
static char *OsLsGetFullpath(const char *path, struct dirent *pdirent)
{
char *fullpath = NULL;
int ret;
if (path[1] != '\0') {
fullpath = (char *)malloc(strlen(path) + strlen(pdirent->d_name) + 2);
if (fullpath == NULL) {
goto exit_with_nomem;
}
ret = snprintf_s(fullpath, strlen(path) + strlen(pdirent->d_name) + 2,
strlen(path) + strlen(pdirent->d_name) + 1, "%s/%s", path, pdirent->d_name);
if (ret < 0) {
free(fullpath);
return NULL;
}
} else {
fullpath = (char *)malloc(strlen(pdirent->d_name) + 2);
if (fullpath == NULL) {
goto exit_with_nomem;
}
ret = snprintf_s(fullpath, strlen(pdirent->d_name) + 2, strlen(pdirent->d_name) + 1,
"/%s", pdirent->d_name);
if (ret < 0) {
free(fullpath);
return NULL;
}
}
return fullpath;
exit_with_nomem:
return (char *)NULL;
}
void OsLs(const char *pathname)
{
struct dirent *pdirent = NULL;
char *path = NULL;
char *fullpath = NULL;
char *fullpathBak = NULL;
int ret;
struct stat statInfo = { 0 };
DIR *d = NULL;
/* list all directory and file */
if (pathname == NULL) {
path = strdup("/");
if (path == NULL) {
return;
}
} else {
ret = VfsNormalizePath(NULL, pathname, &path);
if (ret < 0) {
SetErrno(-ret);
return;
}
}
d = opendir(path);
if (d == NULL) {
PRINT_ERR("No such directory = %s\n", path);
} else {
PRINTK("Directory %s:\n", path);
do {
pdirent = readdir(d);
if (pdirent != NULL) {
(void)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat));
fullpath = OsLsGetFullpath(path, pdirent);
if (fullpath == NULL) {
free(path);
(void)closedir(d);
return;
}
fullpathBak = fullpath;
if (stat(fullpath, &statInfo) == 0) {
PRINTK("%-20s", pdirent->d_name);
if (S_ISDIR(statInfo.st_mode)) {
PRINTK(" %-25s\n", "<DIR>");
} else {
PRINTK(" %-25lu\n", statInfo.st_size);
}
} else {
PRINTK("BAD file: %s\n", pdirent->d_name);
}
free(fullpathBak);
}
} while (pdirent != NULL);
(void)closedir(d);
}
}
int OsShellCmdLs(int argc, const char **argv)
{
char *fullpath = NULL;
const char *filename = NULL;
int ret;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1);
if (argc == 0) {
OsLs(shellWorkingDirectory);
return 0;
}
filename = argv[0];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "ls error"), return -1);
OsLs(fullpath);
free(fullpath);
return 0;
}
int OsShellCmdCd(int argc, const char **argv)
{
if (argc == 0) {
(void)OsShellCmdDoChdir("/");
return 0;
}
OsShellCmdDoChdir(argv[0]);
return 0;
}
#define CAT_BUF_SIZE 512
#define CAT_TASK_PRIORITY 10
#define CAT_TASK_STACK_SIZE 0x3000
pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER;
int OsShellCmdCat(int argc, const char **argv)
{
char *fullpath = NULL;
int ret;
CHAR buf[CAT_BUF_SIZE];
size_t size;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1);
ret = VfsNormalizePath(shellWorkingDirectory, argv[0], &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "cat error"), return -1);
int fd = open(fullpath, O_RDONLY, 0666);
if (fd == -1) {
ret = -1;
return ret;
}
do {
(void)memset_s(buf, sizeof(buf), 0, CAT_BUF_SIZE);
size = read(fd, buf, CAT_BUF_SIZE - 1);
if ((int)size < 0) {
free(fullpath);
close(fd);
return -1;
}
PRINTK("%s", buf);
(void)LOS_TaskDelay(1);
} while (size == CAT_BUF_SIZE);
free(fullpath);
close(fd);
return ret;
}
int OsShellCmdMkdir(int argc, const char **argv)
{
int ret;
char *fullpath = NULL;
const char *filename = NULL;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc != 1, PRINTK("mkdir [DIRECTORY]\n"), return 0);
filename = argv[0];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "mkdir error"), return -1);
ret = mkdir(fullpath, S_IRWXU | S_IRWXG | S_IRWXO);
if (ret == -1) {
perror("mkdir error");
}
free(fullpath);
return 0;
}
int OsShellCmdPwd(int argc, const char **argv)
{
char buf[SHOW_MAX_LEN] = {0};
DIR *dir = NULL;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: pwd\n"), return -1);
LOS_TaskLock();
if (strncpy_s(buf, SHOW_MAX_LEN, shellWorkingDirectory, SHOW_MAX_LEN - 1) != EOK) {
LOS_TaskUnlock();
PRINTK("pwd error: strncpy_s error!\n");
return -1;
}
LOS_TaskUnlock();
PRINTK("%s\n", buf);
return 0;
}
int OsShellCmdTouch(int argc, const char **argv)
{
int ret;
int fd = -1;
char *fullpath = NULL;
const char *filename = NULL;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc != 1, PRINTK("touch [FILE]\n"), return -1);
filename = argv[0];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "touch error"), return -1);
fd = open(fullpath, O_RDWR | O_CREAT, 0777);
free(fullpath);
if (fd == -1) {
perror("touch error");
return -1;
}
(void)close(fd);
return 0;
}
#define CP_BUF_SIZE 4096
pthread_mutex_t g_mutexCp = PTHREAD_MUTEX_INITIALIZER;
static int OsShellCmdDoCp(const char *srcFilePath, const char *dstFileName)
{
int ret;
char *srcFullPath = NULL;
char *drcFullPath = NULL;
const char *srcFileName = NULL;
char *dstFilePath = NULL;
char *buf = NULL;
const char *filename = NULL;
size_t rdSize, wrSize;
int srcFd = -1;
int dstFd = -1;
struct stat statBuf;
mode_t srcMode;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
buf = (char *)malloc(CP_BUF_SIZE);
if (buf == NULL) {
PRINTK("cp error: Out of memory!\n");
return -1;
}
/* Get source fullpath. */
ret = VfsNormalizePath(shellWorkingDirectory, srcFilePath, &srcFullPath);
if (ret < 0) {
SetErrno(-ret);
PRINTK("cp error: %s\n", strerror(errno));
free(buf);
return -1;
}
/* Is source path exist? */
ret = stat(srcFullPath, &statBuf);
if (ret == -1) {
PRINTK("cp %s error: %s\n", srcFullPath, strerror(errno));
goto errout_with_srcpath;
}
srcMode = statBuf.st_mode;
/* Is source path a directory? */
if (S_ISDIR(statBuf.st_mode)) {
PRINTK("cp %s error: Source file can't be a directory.\n", srcFullPath);
goto errout_with_srcpath;
}
/* Get dest fullpath. */
drcFullPath = strdup(dstFileName);
if (drcFullPath == NULL) {
PRINTK("cp error: Out of memory.\n");
goto errout_with_srcpath;
}
/* Is dest path exist? */
ret = stat(drcFullPath, &statBuf);
if (ret == 0) {
/* Is dest path a directory? */
if (S_ISDIR(statBuf.st_mode)) {
/* Get source file name without '/'. */
srcFileName = srcFilePath;
while (1) {
filename = strchr(srcFileName, '/');
if (filename == NULL) {
break;
}
srcFileName = filename + 1;
}
/* Add the source file after dest path. */
ret = VfsNormalizePath(drcFullPath, srcFileName, &dstFilePath);
if (ret < 0) {
SetErrno(-ret);
PRINTK("cp error. %s.\n", strerror(errno));
goto errout_with_path;
}
free(drcFullPath);
drcFullPath = dstFilePath;
}
}
/* Is dest file same as source file? */
if (strcmp(srcFullPath, drcFullPath) == 0) {
PRINTK("cp error: '%s' and '%s' are the same file\n", srcFullPath, drcFullPath);
goto errout_with_path;
}
/* Copy begins. */
(void)pthread_mutex_lock(&g_mutexCp);
srcFd = open(srcFullPath, O_RDONLY);
if (srcFd < 0) {
PRINTK("cp error: can't open %s. %s.\n", srcFullPath, strerror(errno));
goto errout_with_mutex;
}
dstFd = open(drcFullPath, O_CREAT | O_WRONLY | O_TRUNC, srcMode);
if (dstFd < 0) {
PRINTK("cp error: can't create %s. %s.\n", drcFullPath, strerror(errno));
goto errout_with_srcfd;
}
do {
(void)memset_s(buf, CP_BUF_SIZE, 0, CP_BUF_SIZE);
rdSize = read(srcFd, buf, CP_BUF_SIZE);
if (rdSize < 0) {
PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
goto errout_with_fd;
}
wrSize = write(dstFd, buf, rdSize);
if (wrSize != rdSize) {
PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
goto errout_with_fd;
}
} while (rdSize == CP_BUF_SIZE);
/* Release resource. */
free(buf);
free(srcFullPath);
free(drcFullPath);
(void)close(srcFd);
(void)close(dstFd);
(void)pthread_mutex_unlock(&g_mutexCp);
return LOS_OK;
errout_with_fd:
(void)close(dstFd);
errout_with_srcfd:
(void)close(srcFd);
errout_with_mutex:
(void)pthread_mutex_unlock(&g_mutexCp);
errout_with_path:
free(drcFullPath);
errout_with_srcpath:
free(srcFullPath);
free(buf);
return -1;
}
/* The separator and EOF for a directory fullpath: '/'and '\0' */
#define SEPARATOR_EOF_LEN 2
static int OsShellCmdDoRmdir(const char *pathname)
{
struct dirent *dirent = NULL;
struct stat statInfo;
DIR *d = NULL;
char *fullpath = NULL;
int ret;
(void)memset_s(&statInfo, sizeof(statInfo), 0, sizeof(struct stat));
if (stat(pathname, &statInfo) != 0) {
return -1;
}
if (S_ISREG(statInfo.st_mode) || S_ISLNK(statInfo.st_mode)) {
return remove(pathname);
}
d = opendir(pathname);
if (d == NULL) {
return -1;
}
while (1) {
dirent = readdir(d);
if (dirent == NULL) {
break;
}
if (strcmp(dirent->d_name, "..") && strcmp(dirent->d_name, ".")) {
size_t fullPathBufSize = strlen(pathname) + strlen(dirent->d_name) + SEPARATOR_EOF_LEN;
if (fullPathBufSize <= 0) {
PRINTK("buffer size is invalid!\n");
(void)closedir(d);
return -1;
}
fullpath = (char *)malloc(fullPathBufSize);
if (fullpath == NULL) {
PRINTK("malloc failure!\n");
(void)closedir(d);
return -1;
}
ret = snprintf_s(fullpath, fullPathBufSize, fullPathBufSize - 1, "%s/%s", pathname, dirent->d_name);
if (ret < 0) {
PRINTK("name is too long!\n");
free(fullpath);
(void)closedir(d);
return -1;
}
(void)OsShellCmdDoRmdir(fullpath);
free(fullpath);
}
}
(void)closedir(d);
return rmdir(pathname);
}
/* Wildcard matching operations */
static int OsWildcardMatch(const char *src, const char *filename)
{
int ret;
if (*src != '\0') {
if (*filename == '*') {
while ((*filename == '*') || (*filename == '?')) {
filename++;
}
if (*filename == '\0') {
return 0;
}
while (*src != '\0' && !(*src == *filename)) {
src++;
}
if (*src == '\0') {
return -1;
}
ret = OsWildcardMatch(src, filename);
while ((ret != 0) && (*(++src) != '\0')) {
if (*src == *filename) {
ret = OsWildcardMatch(src, filename);
}
}
return ret;
} else {
if ((*src == *filename) || (*filename == '?')) {
return OsWildcardMatch(++src, ++filename);
}
return -1;
}
}
while (*filename != '\0') {
if (*filename != '*') {
return -1;
}
filename++;
}
return 0;
}
/* To determine whether a wildcard character exists in a path */
static int OsIsContainersWildcard(const char *filename)
{
while (*filename != '\0') {
if ((*filename == '*') || (*filename == '?')) {
return 1;
}
filename++;
}
return 0;
}
/* Delete a matching file or directory */
static int OsWildcardDeleteFileOrDir(const char *fullpath, wildcard_type mark)
{
int ret;
switch (mark) {
case RM_RECURSIVER:
ret = OsShellCmdDoRmdir(fullpath);
break;
case RM_FILE:
ret = unlink(fullpath);
break;
case RM_DIR:
ret = rmdir(fullpath);
break;
default:
return VFS_ERROR;
}
if (ret == -1) {
PRINTK("%s ", fullpath);
perror("rm/rmdir error!");
return ret;
}
PRINTK("%s match successful!delete!\n", fullpath);
return 0;
}
/* Split the path with wildcard characters */
static char* OsWildcardSplitPath(char *fullpath, char **handle, char **wait)
{
int n;
int a = 0;
int b = 0;
int len = strlen(fullpath);
for (n = 0; n < len; n++) {
if (fullpath[n] == '/') {
if (b != 0) {
fullpath[n] = '\0';
*wait = fullpath + n + 1;
break;
}
a = n;
} else if (fullpath[n] == '*' || fullpath[n] == '?') {
b = n;
fullpath[a] = '\0';
if (a == 0) {
*handle = fullpath + a + 1;
continue;
}
*handle = fullpath + a + 1;
}
}
return fullpath;
}
/* Handling entry of the path with wildcard characters */
static int OsWildcardExtractDirectory(char *fullpath, void *dst, wildcard_type mark)
{
char separator[] = "/";
char src[PATH_MAX] = {0};
struct dirent *dirent = NULL;
char *f = NULL;
char *s = NULL;
char *t = NULL;
int ret = 0;
DIR *d = NULL;
struct stat statBuf;
int deleteFlag = 0;
f = OsWildcardSplitPath(fullpath, &s, &t);
if (s == NULL) {
if (mark == CP_FILE) {
ret = OsShellCmdDoCp(fullpath, dst);
} else if (mark == CP_COUNT) {
ret = stat(fullpath, &statBuf);
if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
(*(int *)dst)++;
}
} else {
ret = OsWildcardDeleteFileOrDir(fullpath, mark);
}
return ret;
}
d = (*f == '\0') ? opendir("/") : opendir(f);
if (d == NULL) {
perror("opendir error");
return VFS_ERROR;
}
while (1) {
dirent = readdir(d);
if (dirent == NULL) {
break;
}
ret = strcpy_s(src, PATH_MAX, f);
if (ret != EOK) {
goto closedir_out;
}
ret = OsWildcardMatch(dirent->d_name, s);
if (ret == 0) {
ret = strcat_s(src, sizeof(src), separator);
if (ret != EOK) {
goto closedir_out;
}
ret = strcat_s(src, sizeof(src), dirent->d_name);
if (ret != EOK) {
goto closedir_out;
}
if (t == NULL) {
if (mark == CP_FILE) {
ret = OsShellCmdDoCp(src, dst);
} else if (mark == CP_COUNT) {
ret = stat(src, &statBuf);
if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
(*(int *)dst)++;
if ((*(int *)dst) > 1) {
break;
}
}
} else {
ret = OsWildcardDeleteFileOrDir(src, mark);
if (ret == 0) {
deleteFlag = 1;
}
}
} else {
ret = strcat_s(src, sizeof(src), separator);
if (ret != EOK) {
goto closedir_out;
}
ret = strcat_s(src, sizeof(src), t);
if (ret != EOK) {
goto closedir_out;
}
ret = OsWildcardExtractDirectory(src, dst, mark);
if (mark == CP_COUNT && (*(int *)dst) > 1) {
break;
}
}
}
}
(void)closedir(d);
if (deleteFlag == 1) {
ret = 0;
}
return ret;
closedir_out:
(void)closedir(d);
return VFS_ERROR;
}
int OsShellCmdCp(int argc, const char **argv)
{
int ret;
const char *src = NULL;
const char *dst = NULL;
char *srcFullPath = NULL;
char *drcFullPath = NULL;
struct stat statBuf;
int count = 0;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1);
src = argv[0];
dst = argv[1];
/* Get source fullpath. */
ret = VfsNormalizePath(shellWorkingDirectory, src, &srcFullPath);
if (ret < 0) {
SetErrno(-ret);
PRINTK("cp error:%s\n", strerror(errno));
return -1;
}
if (src[strlen(src) - 1] == '/') {
PRINTK("cp %s error: Source file can't be a directory.\n", src);
goto errout_with_srcpath;
}
/* Get dest fullpath. */
ret = VfsNormalizePath(shellWorkingDirectory, dst, &drcFullPath);
if (ret < 0) {
SetErrno(-ret);
PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno));
goto errout_with_srcpath;
}
/* Is dest path exist? */
ret = stat(drcFullPath, &statBuf);
if (ret < 0) {
/* Is dest path a directory? */
if (dst[strlen(dst) - 1] == '/') {
PRINTK("cp error: %s, %s.\n", drcFullPath, strerror(errno));
goto errout_with_path;
}
} else {
if ((S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) && dst[strlen(dst) - 1] == '/') {
PRINTK("cp error: %s is not a directory.\n", drcFullPath);
goto errout_with_path;
}
}
if (OsIsContainersWildcard(srcFullPath)) {
if (ret < 0 || S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) {
char *srcCopy = strdup(srcFullPath);
if (srcCopy == NULL) {
PRINTK("cp error : Out of memory.\n");
goto errout_with_path;
}
(void)OsWildcardExtractDirectory(srcCopy, &count, CP_COUNT);
free(srcCopy);
if (count > 1) {
PRINTK("cp error : %s is not a directory.\n", drcFullPath);
goto errout_with_path;
}
}
ret = OsWildcardExtractDirectory(srcFullPath, drcFullPath, CP_FILE);
} else {
ret = OsShellCmdDoCp(srcFullPath, drcFullPath);
}
free(drcFullPath);
free(srcFullPath);
return ret;
errout_with_path:
free(drcFullPath);
errout_with_srcpath:
free(srcFullPath);
return VFS_ERROR;
}
static inline void PrintRmUsage(void)
{
PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
}
int OsShellCmdRm(int argc, const char **argv)
{
int ret;
char *fullpath = NULL;
const char *filename = NULL;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc != 1 && argc != 2, PrintRmUsage(), return -1);
if (argc == 2) {
ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, PrintRmUsage(), return -1);
filename = argv[1];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
if (OsIsContainersWildcard(fullpath)) {
ret = OsWildcardExtractDirectory(fullpath, NULL, RM_RECURSIVER);
} else {
ret = OsShellCmdDoRmdir(fullpath);
}
} else {
filename = argv[0];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
if (OsIsContainersWildcard(fullpath)) {
ret = OsWildcardExtractDirectory(fullpath, NULL, RM_FILE);
} else {
ret = unlink(fullpath);
}
}
if (ret == -1) {
perror("rm error");
}
free(fullpath);
return 0;
}
int OsShellCmdRmdir(int argc, const char **argv)
{
int ret;
char *fullpath = NULL;
const char *filename = NULL;
char *shellWorkingDirectory = OsShellGetWorkingDirtectory();
if (shellWorkingDirectory == NULL) {
return -1;
}
ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1);
filename = argv[0];
ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
ERROR_OUT_IF(ret < 0, SetErr(-ret, "rmdir error"), return -1);
if (OsIsContainersWildcard(fullpath)) {
ret = OsWildcardExtractDirectory(fullpath, NULL, RM_DIR);
} else {
ret = rmdir(fullpath);
}
if (ret == -1) {
PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno));
}
free(fullpath);
return 0;
}