openharmony_kernel_liteos_a/shell/full/src/cmds/watch_shellcmd.c

277 lines
8.7 KiB
C

/*
* 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 "shmsg.h"
#include "unistd.h"
#include "stdio.h"
#include "time.h"
#include "los_event.h"
#include "los_tick.h"
#include "securec.h"
#define timeval64 timeval
#define gettimeofday64 gettimeofday
#define ctime64 ctime
#ifdef LOSCFG_SHELL_CMD_DEBUG
typedef struct {
BOOL title; /* whether to hide the timestamps */
UINT32 count; /* the total number of command executions */
UINT32 interval; /* running cycle of the command */
EVENT_CB_S watchEvent; /* event handle of the watch structure */
CHAR cmdbuf[CMD_MAX_LEN]; /* the command to watch */
} WatchCB;
STATIC WatchCB *g_watchCmd;
#define WATCH_COUNT_MAX 0xFFFFFF
#define WATCH_INTERTVAL_MAX 0xFFFFFF
STATIC VOID PrintTime(VOID)
{
struct timeval64 stNowTime = {0};
if (gettimeofday64(&stNowTime, NULL) == 0) {
PRINTK("%s", ctime64(&(stNowTime.tv_sec)));
}
}
STATIC VOID OsShellCmdDoWatch(UINTPTR arg1)
{
WatchCB *watchItem = (WatchCB *)arg1;
UINT32 ret;
g_watchCmd = watchItem;
while (watchItem->count--) {
printf("\033[2J\n");
if (watchItem->title) {
PrintTime();
}
(VOID)ShellMsgParse(watchItem->cmdbuf);
ret = LOS_EventRead(&watchItem->watchEvent, 0x01, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, watchItem->interval);
if (ret == 0x01) {
break;
}
}
(VOID)LOS_EventDestroy(&watchItem->watchEvent);
free(g_watchCmd);
g_watchCmd = NULL;
}
STATIC INLINE VOID OsWatchCmdUsage(VOID)
{
PRINTK("\nUsage: watch\n");
PRINTK("watch [options] command\n");
}
STATIC UINT32 OsWatchOverFunc(VOID)
{
UINT32 ret;
if (g_watchCmd != NULL) {
ret = LOS_EventWrite(&g_watchCmd->watchEvent, 0x01);
if (ret != LOS_OK) {
PRINT_ERR("Write event failed in %s,%d\n", __FUNCTION__, __LINE__);
return OS_ERROR;
}
return LOS_OK;
} else {
PRINTK("No watch task to turn off.\n");
return OS_ERROR;
}
}
INT32 OsWatchOptionParsed(UINT32 argc, UINT32 *argoff, const CHAR **argv, WatchCB *watchItem)
{
long tmpVal;
CHAR *strPtr = NULL;
UINT32 argcount = argc;
while (argv[*argoff][0] == '-') {
if (argcount <= 1) {
OsWatchCmdUsage();
return -1;
}
if ((strcmp(argv[*argoff], "-n") == 0) || (strcmp(argv[*argoff], "--interval") == 0)) {
if (argcount <= 2) { /* 2:count of parameter */
OsWatchCmdUsage();
return -1;
}
tmpVal = (long)strtoul(argv[*argoff + 1], &strPtr, 0);
if ((*strPtr != 0) || (tmpVal <= 0) || (tmpVal > WATCH_INTERTVAL_MAX)) {
PRINTK("\ninterval time is invalid\n");
OsWatchCmdUsage();
return -1;
}
watchItem->interval = g_tickPerSecond * (UINT32)tmpVal;
argcount -= 2; /* 2:offset of argv */
(*argoff) += 2; /* 2:offset of argv */
} else if ((strcmp(argv[*argoff], "-t") == 0) || (strcmp(argv[*argoff], "-no-title") == 0)) {
watchItem->title = FALSE;
argcount--;
(*argoff)++;
} else if ((strcmp(argv[*argoff], "-c") == 0) || (strcmp(argv[*argoff], "--count") == 0)) {
if (argcount <= 2) { /* 2:count of parameter */
OsWatchCmdUsage();
return -1;
}
tmpVal = (long)strtoul(argv[*argoff + 1], &strPtr, 0);
if ((*strPtr != 0) || (tmpVal <= 0) || (tmpVal > WATCH_COUNT_MAX)) {
PRINTK("\ncount is invalid\n");
OsWatchCmdUsage();
return -1;
}
watchItem->count = (UINT32)tmpVal;
argcount -= 2; /* 2:offset of argv */
(*argoff) += 2; /* 2:offset of argv */
} else {
PRINTK("Unknown option.\n");
return -1;
}
}
return 0;
}
INT32 OsWatchCmdSplice(UINT32 argc, UINT32 argoff, const CHAR **argv, WatchCB *watchItem)
{
INT32 err = 0;
if ((argc - argoff) == 0) {
PRINT_ERR("no watch command!\n");
return -1;
}
while (argc - argoff) {
err = strcat_s(watchItem->cmdbuf, sizeof(watchItem->cmdbuf), argv[argoff]);
if (err != EOK) {
PRINT_ERR("%s, %d strcat_s failed!\n", __FUNCTION__, __LINE__);
return -1;
}
err = strcat_s(watchItem->cmdbuf, sizeof(watchItem->cmdbuf), " ");
if (err != EOK) {
PRINT_ERR("%s, %d strcat_s failed!\n", __FUNCTION__, __LINE__);
return -1;
}
argoff++;
}
return err;
}
UINT32 OsWatchTaskCreate(WatchCB *watchItem)
{
TSK_INIT_PARAM_S initParam = {0};
UINT32 watchTaskId = 0;
UINT32 ret;
ret = LOS_EventInit(&watchItem->watchEvent);
if (ret != 0) {
PRINT_ERR("Watch event init failed in %s, %d\n", __FUNCTION__, __LINE__);
return ret;
}
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsShellCmdDoWatch;
initParam.usTaskPrio = 10; /* 10:shellcmd_watch task priority */
initParam.auwArgs[0] = (UINTPTR)watchItem;
initParam.uwStackSize = 0x3000; /* 0x3000:stack size of shellcmd_watch task */
initParam.pcName = "shellcmd_watch";
initParam.uwResved = LOS_TASK_STATUS_DETACHED;
ret = LOS_TaskCreate(&watchTaskId, &initParam);
if (ret != 0) {
PRINT_ERR("Watch task init failed in %s, %d\n", __FUNCTION__, __LINE__);
return ret;
}
return ret;
}
UINT32 OsShellCmdWatch(UINT32 argc, const CHAR **argv)
{
WatchCB *watchItem = NULL;
UINT32 argoff = 0;
UINT32 ret;
INT32 err;
if (argc == 0) {
OsWatchCmdUsage();
return OS_ERROR;
}
if (argv == NULL) {
OsWatchCmdUsage();
return OS_ERROR;
}
if ((argc == 1) && (strcmp(argv[0], "--over") == 0)) {
ret = OsWatchOverFunc();
return ret;
}
if (g_watchCmd != NULL) {
PRINTK("Please turn off previous watch before to start a new watch.\n");
return OS_ERROR;
}
watchItem = (WatchCB *)malloc(sizeof(WatchCB));
if (watchItem == NULL) {
PRINTK("Malloc error!\n");
return OS_ERROR;
}
(VOID)memset_s(watchItem, sizeof(WatchCB), 0, sizeof(WatchCB));
watchItem->title = TRUE;
watchItem->count = WATCH_COUNT_MAX;
watchItem->interval = g_tickPerSecond;
err = OsWatchOptionParsed(argc, &argoff, argv, watchItem);
if (err != 0) {
goto WATCH_ERROR;
}
err = OsWatchCmdSplice(argc, argoff, argv, watchItem);
if (err != 0) {
goto WATCH_ERROR;
}
ret = OsWatchTaskCreate(watchItem);
if (ret != 0) {
goto WATCH_ERROR;
}
return LOS_OK;
WATCH_ERROR:
free(watchItem);
return OS_ERROR;
}
SHELLCMD_ENTRY(watch_shellcmd, CMD_TYPE_EX, "watch", XARGS, (CmdCallBackFunc)OsShellCmdWatch);
#endif