1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common_event_command.h"
17
18 #include <getopt.h>
19
20 #include "common_event.h"
21 #include "common_event_constant.h"
22 #include "common_event_manager.h"
23 #include "event_log_wrapper.h"
24 #include "singleton.h"
25
26 namespace OHOS {
27 namespace EventFwk {
28 namespace {
29 const std::string SHORT_OPTIONS = "he:asoc:d:u:";
30 const struct option LONG_OPTIONS[] = {
31 {"help", no_argument, nullptr, 'h'},
32 {"all", no_argument, nullptr, 'a'},
33 {"event", required_argument, nullptr, 'e'},
34 {"sticky", no_argument, nullptr, 's'},
35 {"ordered", no_argument, nullptr, 'o'},
36 {"code", required_argument, nullptr, 'c'},
37 {"data", required_argument, nullptr, 'd'},
38 {"user-id", required_argument, nullptr, 'u'},
39 };
40 } // namespace
41
CommonEventCommand(int argc,char * argv[])42 CommonEventCommand::CommonEventCommand(int argc, char *argv[])
43 : ShellCommand(argc, argv, TOOL_NAME)
44 {
45 EVENT_LOGI("enter");
46
47 for (int i = 0; i < argc_; i++) {
48 EVENT_LOGI("argv_[%{public}d]: %{public}s", i, argv_[i]);
49 }
50 }
51
CreateCommandMap()52 ErrCode CommonEventCommand::CreateCommandMap()
53 {
54 commandMap_ = {
55 {"help", std::bind(&CommonEventCommand::RunAsHelpCommand, this)},
56 {"publish", std::bind(&CommonEventCommand::RunAsPublishCommand, this)},
57 {"dump", std::bind(&CommonEventCommand::RunAsDumpCommand, this)},
58 };
59
60 return OHOS::ERR_OK;
61 }
62
CreateMessageMap()63 ErrCode CommonEventCommand::CreateMessageMap()
64 {
65 messageMap_ = {};
66
67 return OHOS::ERR_OK;
68 }
69
init()70 ErrCode CommonEventCommand::init()
71 {
72 EVENT_LOGI("enter");
73
74 ErrCode result = OHOS::ERR_OK;
75
76 if (!commonEventPtr_) {
77 commonEventPtr_ = DelayedSingleton<CommonEvent>::GetInstance();
78 }
79
80 if (!commonEventPtr_) {
81 result = OHOS::ERR_INVALID_VALUE;
82 }
83
84 return result;
85 }
86
RunAsHelpCommand()87 ErrCode CommonEventCommand::RunAsHelpCommand()
88 {
89 EVENT_LOGI("enter");
90
91 resultReceiver_.append(HELP_MSG);
92
93 return OHOS::ERR_OK;
94 }
95
RunAsPublishCommand()96 ErrCode CommonEventCommand::RunAsPublishCommand()
97 {
98 EVENT_LOGI("enter");
99
100 ErrCode result = OHOS::ERR_OK;
101
102 int option = -1;
103 std::int32_t userId = ALL_USER;
104 int counter = 0;
105
106 bool isSticky = false;
107 bool isOrdered = false;
108
109 std::string action = "";
110 int code = 0;
111 std::string data = "";
112
113 while (true) {
114 counter++;
115
116 option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
117
118 EVENT_LOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
119
120 if (optind < 0 || optind > argc_) {
121 return OHOS::ERR_INVALID_VALUE;
122 }
123
124 for (int i = 0; i < argc_; i++) {
125 EVENT_LOGI("argv_[%{public}d]: %{public}s", i, argv_[i]);
126 }
127
128 if (option == -1) {
129 if (counter == 1) {
130 // When scanning the first argument
131 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
132 // 'cem publish' with no option: cem publish
133 // 'cem publish' with a wrong argument: cem publish xxx
134 EVENT_LOGI("'cem publish' with no option.");
135
136 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
137
138 result = OHOS::ERR_INVALID_VALUE;
139 }
140 }
141 break;
142 }
143
144 if (option == '?') {
145 switch (optopt) {
146 case 'e': {
147 // 'cem publish -e' with no argument: cem publish -e
148 // 'cem publish --event' with no argument: cem publish --event
149 EVENT_LOGI("'cem publish -e' with no argument.");
150
151 resultReceiver_.append("error: option ");
152 resultReceiver_.append("requires a value.\n");
153
154 result = OHOS::ERR_INVALID_VALUE;
155 break;
156 }
157 case 'c': {
158 // 'cem publish -e <name> -c' with no argument: cem publish -e <name> -c
159 // 'cem publish --event <name> -c' with no argument: cem publish --event -c
160 EVENT_LOGI("'cem publish -e <name> -c' with no argument.");
161
162 resultReceiver_.append("error: option ");
163 resultReceiver_.append("requires a value.\n");
164
165 result = OHOS::ERR_INVALID_VALUE;
166 break;
167 }
168 case 'd': {
169 // 'cem publish -e <name> -d' with no argument: cem publish -e <name> -d
170 // 'cem publish --event <name> -d' with no argument: cem publish --event -d
171 EVENT_LOGI("'cem publish -e <name> -d' with no argument.");
172
173 resultReceiver_.append("error: option ");
174 resultReceiver_.append("requires a value.\n");
175
176 result = OHOS::ERR_INVALID_VALUE;
177 break;
178 }
179 case 'u':
180 // 'cem publish -e <name> -u' with no argument: cem publish -e <name> -d
181 // 'cem publish --event <name> -d' with no argument: cem publish --event -d
182 EVENT_LOGI("'cem publish -e <name> -u' with no argument.");
183
184 resultReceiver_.append("error: option ");
185 resultReceiver_.append("requires a value.\n");
186
187 result = OHOS::ERR_INVALID_VALUE;
188 break;
189 case 0: {
190 // 'cem publish' with an unknown option: cem publish --x
191 // 'cem publish' with an unknown option: cem publish --xxx
192 std::string unknownOption = "";
193 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
194
195 EVENT_LOGI("'cem publish' with an unknown option.");
196
197 resultReceiver_.append(unknownOptionMsg);
198 result = OHOS::ERR_INVALID_VALUE;
199 break;
200 }
201 default: {
202 // 'cem publish' with an unknown option: cem publish -x
203 // 'cem publish' with an unknown option: cem publish -xxx
204 std::string unknownOption = "";
205 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
206
207 EVENT_LOGI("'cem publish' with an unknown option.");
208
209 resultReceiver_.append(unknownOptionMsg);
210 result = OHOS::ERR_INVALID_VALUE;
211 break;
212 }
213 }
214 break;
215 }
216
217 switch (option) {
218 case 'h': {
219 // 'cem publish -h'
220 // 'cem publish --help'
221 result = OHOS::ERR_INVALID_VALUE;
222 break;
223 }
224 case 'e': {
225 // 'cem publish -e <name>'
226 // 'cem publish --event <name>'
227 action = optarg;
228 break;
229 }
230 case 's': {
231 // 'cem publish -e <name> -s '
232 // 'cem publish -e <name> --sticky'
233 isSticky = true;
234 break;
235 }
236 case 'o': {
237 // 'cem publish -e <name> -o '
238 // 'cem publish -e <name> --ordered'
239 isOrdered = true;
240 break;
241 }
242 case 'c': {
243 // 'cem publish -e <name> -c 1024 '
244 // 'cem publish -e <name> --code 1024'
245 code = atoi(optarg);
246 break;
247 }
248 case 'd': {
249 // 'cem publish -e <name> -d 1024 '
250 // 'cem publish -e <name> --data 1024'
251 data = optarg;
252 break;
253 }
254 case 'u': {
255 // 'cem publish -e <name> -u 100'
256 // 'cem publish --event <name> -u 100'
257 userId = atoi(optarg);
258 break;
259 }
260 case 0: {
261 break;
262 }
263 default: {
264 break;
265 }
266 }
267 }
268
269 if (result == OHOS::ERR_OK) {
270 if (resultReceiver_ == "" && action.size() == 0) {
271 // 'cem publish ...' with no event option
272 EVENT_LOGI("'cem publish' with no event option.");
273
274 resultReceiver_.append(HELP_MSG_NO_EVENT_OPTION + "\n");
275 result = OHOS::ERR_INVALID_VALUE;
276 }
277 }
278
279 if (result != OHOS::ERR_OK) {
280 resultReceiver_.append(HELP_MSG_PUBLISH);
281 } else {
282 /* Publish */
283
284 // make a want
285 Want want;
286 want.SetAction(action);
287
288 // make common event data
289 CommonEventData commonEventData;
290 commonEventData.SetWant(want);
291
292 // set code
293 commonEventData.SetCode(code);
294
295 // set data
296 commonEventData.SetData(data);
297
298 // make publish info
299 CommonEventPublishInfo publishInfo;
300 publishInfo.SetSticky(isSticky);
301 publishInfo.SetOrdered(isOrdered);
302
303 // publish the common event
304 std::shared_ptr<CommonEventSubscriber> subscriber = nullptr;
305 bool publishResult = commonEventPtr_->PublishCommonEventAsUser(
306 commonEventData, publishInfo, subscriber, userId);
307 if (publishResult) {
308 resultReceiver_ = STRING_PUBLISH_COMMON_EVENT_OK + "\n";
309 } else {
310 resultReceiver_ = STRING_PUBLISH_COMMON_EVENT_NG + "\n";
311 }
312 }
313
314 return result;
315 }
316
RunAsDumpCommand()317 ErrCode CommonEventCommand::RunAsDumpCommand()
318 {
319 EVENT_LOGI("enter");
320
321 ErrCode result = OHOS::ERR_OK;
322 std::vector<std::string> dumpResults;
323
324 std::string action = "";
325 std::int32_t userId = ALL_USER;
326
327 int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
328
329 EVENT_LOGI("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
330
331 if (optind < 0 || optind > argc_) {
332 return OHOS::ERR_INVALID_VALUE;
333 }
334
335 for (int i = 0; i < argc_; i++) {
336 EVENT_LOGI("argv_[%{public}d]: %{public}s", i, argv_[i]);
337 }
338
339 switch (option) {
340 case 'h': {
341 // 'cem dump -h'
342 // 'cem dump --help'
343 result = OHOS::ERR_INVALID_VALUE;
344 break;
345 }
346 case 'a': {
347 // 'cem dump -a'
348 // 'cem dump --all'
349 break;
350 }
351 case 'e': {
352 // 'cem dump -e <name>'
353 // 'cem dump --event <name>'
354 action = optarg;
355 break;
356 }
357 case 'u': {
358 // 'cem dump -e <name> -u 100'
359 // 'cem dump --event <name> -u 100'
360 userId = atoi(optarg);
361 break;
362 }
363 case '?': {
364 switch (optopt) {
365 case 'e': {
366 // 'cem dump -e' with no argument: cem dump -e
367 // 'cem dump --event' with no argument: cem dump --event
368 EVENT_LOGI("'cem dump -s' with no argument.");
369
370 resultReceiver_.append("error: option ");
371 resultReceiver_.append("requires a value.\n");
372 result = OHOS::ERR_INVALID_VALUE;
373 break;
374 }
375 case 'u':
376 // 'cem dump -e' with no argument: cem dump -e
377 // 'cem dump --event' with no argument: cem dump --user-id
378 EVENT_LOGI("'cem dump -u' with no argument.");
379
380 resultReceiver_.append("error: option ");
381 resultReceiver_.append("requires a value.\n");
382 result = OHOS::ERR_INVALID_VALUE;
383 break;
384 case 0: {
385 // 'cem dump' with an unknown option: cem dump --x
386 // 'cem dump' with an unknown option: cem dump --xxx
387 std::string unknownOption = "";
388 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
389
390 EVENT_LOGI("'cem dump' with an unknown option.");
391
392 resultReceiver_.append(unknownOptionMsg);
393 result = OHOS::ERR_INVALID_VALUE;
394 break;
395 }
396 default: {
397 // 'cem dump' with an unknown option: cem dump -x
398 // 'cem dump' with an unknown option: cem dump -xxx
399 std::string unknownOption = "";
400 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
401
402 EVENT_LOGI("'cem dump' with an unknown option.");
403
404 resultReceiver_.append(unknownOptionMsg);
405 result = OHOS::ERR_INVALID_VALUE;
406 break;
407 }
408 }
409 break;
410 }
411 default: {
412 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
413 // 'cem dump' with no option: cem dump
414 // 'cem dump' with a wrong argument: cem dump xxx
415 EVENT_LOGI("'cem dump' with no option.");
416
417 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
418 result = OHOS::ERR_INVALID_VALUE;
419 }
420 break;
421 }
422 }
423
424 if (result != OHOS::ERR_OK) {
425 resultReceiver_.append(HELP_MSG_DUMP);
426 } else {
427 // dump state
428 bool dumpResult = commonEventPtr_->DumpState(action, userId, dumpResults);
429 if (dumpResult) {
430 for (auto it : dumpResults) {
431 resultReceiver_ += it + "\n";
432 }
433 } else {
434 resultReceiver_ = STRING_DUMP_COMMON_EVENT_NG + "\n";
435 }
436 }
437
438 return result;
439 }
440 } // namespace EventFwk
441 } // namespace OHOS
442