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 #include "shcmd.h"
33 #include "shmsg.h"
34 #include "unistd.h"
35 #include "stdio.h"
36 #include "time.h"
37 #include "los_event.h"
38 #include "los_tick.h"
39
40 #include "securec.h"
41
42 #define timeval64 timeval
43 #define gettimeofday64 gettimeofday
44 #define ctime64 ctime
45
46 #ifdef LOSCFG_SHELL_CMD_DEBUG
47 typedef struct {
48 BOOL title; /* whether to hide the timestamps */
49 UINT32 count; /* the total number of command executions */
50 UINT32 interval; /* running cycle of the command */
51 EVENT_CB_S watchEvent; /* event handle of the watch structure */
52 CHAR cmdbuf[CMD_MAX_LEN]; /* the command to watch */
53 } WatchCB;
54
55 STATIC WatchCB *g_watchCmd;
56
57 #define WATCH_COUNT_MAX 0xFFFFFF
58 #define WATCH_INTERTVAL_MAX 0xFFFFFF
59
PrintTimenull60 STATIC VOID PrintTime(VOID)
61 {
62 struct timeval64 stNowTime = {0};
63
64 if (gettimeofday64(&stNowTime, NULL) == 0) {
65 PRINTK("%s", ctime64(&(stNowTime.tv_sec)));
66 }
67 }
68
OsShellCmdDoWatch(UINTPTR arg1)69 STATIC VOID OsShellCmdDoWatch(UINTPTR arg1)
70 {
71 WatchCB *watchItem = (WatchCB *)arg1;
72 UINT32 ret;
73 g_watchCmd = watchItem;
74
75 while (watchItem->count--) {
76 printf("\033[2J\n");
77 if (watchItem->title) {
78 PrintTime();
79 }
80 (VOID)ShellMsgParse(watchItem->cmdbuf);
81 ret = LOS_EventRead(&watchItem->watchEvent, 0x01, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, watchItem->interval);
82 if (ret == 0x01) {
83 break;
84 }
85 }
86
87 (VOID)LOS_EventDestroy(&watchItem->watchEvent);
88 free(g_watchCmd);
89 g_watchCmd = NULL;
90 }
91
OsWatchCmdUsagenull92 STATIC INLINE VOID OsWatchCmdUsage(VOID)
93 {
94 PRINTK("\nUsage: watch\n");
95 PRINTK("watch [options] command\n");
96 }
97
OsWatchOverFuncnull98 STATIC UINT32 OsWatchOverFunc(VOID)
99 {
100 UINT32 ret;
101 if (g_watchCmd != NULL) {
102 ret = LOS_EventWrite(&g_watchCmd->watchEvent, 0x01);
103 if (ret != LOS_OK) {
104 PRINT_ERR("Write event failed in %s,%d\n", __FUNCTION__, __LINE__);
105 return OS_ERROR;
106 }
107 return LOS_OK;
108 } else {
109 PRINTK("No watch task to turn off.\n");
110 return OS_ERROR;
111 }
112 }
113
OsWatchOptionParsed(UINT32 argc, UINT32 *argoff, const CHAR **argv, WatchCB *watchItem)114 INT32 OsWatchOptionParsed(UINT32 argc, UINT32 *argoff, const CHAR **argv, WatchCB *watchItem)
115 {
116 long tmpVal;
117 CHAR *strPtr = NULL;
118 UINT32 argcount = argc;
119
120 while (argv[*argoff][0] == '-') {
121 if (argcount <= 1) {
122 OsWatchCmdUsage();
123 return -1;
124 }
125
126 if ((strcmp(argv[*argoff], "-n") == 0) || (strcmp(argv[*argoff], "--interval") == 0)) {
127 if (argcount <= 2) { /* 2:count of parameter */
128 OsWatchCmdUsage();
129 return -1;
130 }
131 tmpVal = (long)strtoul(argv[*argoff + 1], &strPtr, 0);
132 if ((*strPtr != 0) || (tmpVal <= 0) || (tmpVal > WATCH_INTERTVAL_MAX)) {
133 PRINTK("\ninterval time is invalid\n");
134 OsWatchCmdUsage();
135 return -1;
136 }
137 watchItem->interval = g_tickPerSecond * (UINT32)tmpVal;
138 argcount -= 2; /* 2:offset of argv */
139 (*argoff) += 2; /* 2:offset of argv */
140 } else if ((strcmp(argv[*argoff], "-t") == 0) || (strcmp(argv[*argoff], "-no-title") == 0)) {
141 watchItem->title = FALSE;
142 argcount--;
143 (*argoff)++;
144 } else if ((strcmp(argv[*argoff], "-c") == 0) || (strcmp(argv[*argoff], "--count") == 0)) {
145 if (argcount <= 2) { /* 2:count of parameter */
146 OsWatchCmdUsage();
147 return -1;
148 }
149 tmpVal = (long)strtoul(argv[*argoff + 1], &strPtr, 0);
150 if ((*strPtr != 0) || (tmpVal <= 0) || (tmpVal > WATCH_COUNT_MAX)) {
151 PRINTK("\ncount is invalid\n");
152 OsWatchCmdUsage();
153 return -1;
154 }
155 watchItem->count = (UINT32)tmpVal;
156 argcount -= 2; /* 2:offset of argv */
157 (*argoff) += 2; /* 2:offset of argv */
158 } else {
159 PRINTK("Unknown option.\n");
160 return -1;
161 }
162 }
163 return 0;
164 }
165
OsWatchCmdSplice(UINT32 argc, UINT32 argoff, const CHAR **argv, WatchCB *watchItem)166 INT32 OsWatchCmdSplice(UINT32 argc, UINT32 argoff, const CHAR **argv, WatchCB *watchItem)
167 {
168 INT32 err = 0;
169 if ((argc - argoff) == 0) {
170 PRINT_ERR("no watch command!\n");
171 return -1;
172 }
173 while (argc - argoff) {
174 err = strcat_s(watchItem->cmdbuf, sizeof(watchItem->cmdbuf), argv[argoff]);
175 if (err != EOK) {
176 PRINT_ERR("%s, %d strcat_s failed!\n", __FUNCTION__, __LINE__);
177 return -1;
178 }
179 err = strcat_s(watchItem->cmdbuf, sizeof(watchItem->cmdbuf), " ");
180 if (err != EOK) {
181 PRINT_ERR("%s, %d strcat_s failed!\n", __FUNCTION__, __LINE__);
182 return -1;
183 }
184 argoff++;
185 }
186 return err;
187 }
188
OsWatchTaskCreate(WatchCB *watchItem)189 UINT32 OsWatchTaskCreate(WatchCB *watchItem)
190 {
191 TSK_INIT_PARAM_S initParam = {0};
192 UINT32 watchTaskId = 0;
193 UINT32 ret;
194
195 ret = LOS_EventInit(&watchItem->watchEvent);
196 if (ret != 0) {
197 PRINT_ERR("Watch event init failed in %s, %d\n", __FUNCTION__, __LINE__);
198 return ret;
199 }
200
201 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsShellCmdDoWatch;
202 initParam.usTaskPrio = 10; /* 10:shellcmd_watch task priority */
203 initParam.auwArgs[0] = (UINTPTR)watchItem;
204 initParam.uwStackSize = 0x3000; /* 0x3000:stack size of shellcmd_watch task */
205 initParam.pcName = "shellcmd_watch";
206 initParam.uwResved = LOS_TASK_STATUS_DETACHED;
207
208 ret = LOS_TaskCreate(&watchTaskId, &initParam);
209 if (ret != 0) {
210 PRINT_ERR("Watch task init failed in %s, %d\n", __FUNCTION__, __LINE__);
211 return ret;
212 }
213 return ret;
214 }
215
OsShellCmdWatch(UINT32 argc, const CHAR **argv)216 UINT32 OsShellCmdWatch(UINT32 argc, const CHAR **argv)
217 {
218 WatchCB *watchItem = NULL;
219 UINT32 argoff = 0;
220 UINT32 ret;
221 INT32 err;
222
223 if (argc == 0) {
224 OsWatchCmdUsage();
225 return OS_ERROR;
226 }
227
228 if (argv == NULL) {
229 OsWatchCmdUsage();
230 return OS_ERROR;
231 }
232
233 if ((argc == 1) && (strcmp(argv[0], "--over") == 0)) {
234 ret = OsWatchOverFunc();
235 return ret;
236 }
237
238 if (g_watchCmd != NULL) {
239 PRINTK("Please turn off previous watch before to start a new watch.\n");
240 return OS_ERROR;
241 }
242
243 watchItem = (WatchCB *)malloc(sizeof(WatchCB));
244 if (watchItem == NULL) {
245 PRINTK("Malloc error!\n");
246 return OS_ERROR;
247 }
248 (VOID)memset_s(watchItem, sizeof(WatchCB), 0, sizeof(WatchCB));
249 watchItem->title = TRUE;
250 watchItem->count = WATCH_COUNT_MAX;
251 watchItem->interval = g_tickPerSecond;
252
253 err = OsWatchOptionParsed(argc, &argoff, argv, watchItem);
254 if (err != 0) {
255 goto WATCH_ERROR;
256 }
257
258 err = OsWatchCmdSplice(argc, argoff, argv, watchItem);
259 if (err != 0) {
260 goto WATCH_ERROR;
261 }
262
263 ret = OsWatchTaskCreate(watchItem);
264 if (ret != 0) {
265 goto WATCH_ERROR;
266 }
267
268 return LOS_OK;
269
270 WATCH_ERROR:
271 free(watchItem);
272 return OS_ERROR;
273 }
274
275 SHELLCMD_ENTRY(watch_shellcmd, CMD_TYPE_EX, "watch", XARGS, (CmdCallBackFunc)OsShellCmdWatch);
276 #endif
277