1 /*
2  * Copyright (c) 2021-2022 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:p:";
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 
CreateCommandMap()42 ErrCode CommonEventCommand::CreateCommandMap()
43 {
44     commandMap_ = {
45         {"help", std::bind(&CommonEventCommand::RunAsHelpCommand, this)},
46         {"publish", std::bind(&CommonEventCommand::RunAsPublishCommand, this)},
47         {"dump", std::bind(&CommonEventCommand::RunAsDumpCommand, this)},
48     };
49     return ERR_OK;
50 }
51 
RunAsHelpCommand()52 ErrCode CommonEventCommand::RunAsHelpCommand()
53 {
54     EVENT_LOGI("enter");
55     resultReceiver_.append(HELP_MSG);
56     return ERR_OK;
57 }
58 
RunAsPublishCommand()59 ErrCode CommonEventCommand::RunAsPublishCommand()
60 {
61     EVENT_LOGI("enter");
62     ErrCode result = ERR_OK;
63     PublishCmdInfo cmdInfo;
64     bool hasOption = false;
65     SetPublishCmdInfo(cmdInfo, result, hasOption);
66     if (!hasOption) {
67         resultReceiver_.append(HELP_MSG_NO_OPTION);
68         resultReceiver_.append(HELP_MSG_PUBLISH);
69         return ERR_INVALID_VALUE;
70     }
71     if (result == ERR_OK && resultReceiver_.empty() && cmdInfo.action.empty()) {
72         resultReceiver_.append(HELP_MSG_NO_EVENT_OPTION);
73         result = ERR_INVALID_VALUE;
74     }
75     if (result == ERR_OK) {
76         Want want;
77         want.SetAction(cmdInfo.action);
78         CommonEventData commonEventData;
79         commonEventData.SetWant(want);
80         commonEventData.SetCode(cmdInfo.code);
81         commonEventData.SetData(cmdInfo.data);
82         CommonEventPublishInfo publishInfo;
83         publishInfo.SetSticky(cmdInfo.isSticky);
84         publishInfo.SetOrdered(cmdInfo.isOrdered);
85         // publish the common event
86         int32_t publishResult = CommonEvent::GetInstance()->PublishCommonEventAsUser(
87             commonEventData, publishInfo, nullptr, cmdInfo.userId);
88         if (publishResult == ERR_OK) {
89             resultReceiver_ = STRING_PUBLISH_COMMON_EVENT_OK;
90         } else {
91             resultReceiver_ = STRING_PUBLISH_COMMON_EVENT_NG;
92         }
93     } else {
94         resultReceiver_.append(HELP_MSG_PUBLISH);
95     }
96     return result;
97 }
98 
SetPublishCmdInfo(PublishCmdInfo & cmdInfo,ErrCode & result,bool & hasOption)99 void CommonEventCommand::SetPublishCmdInfo(PublishCmdInfo &cmdInfo, ErrCode &result, bool &hasOption)
100 {
101     int option;
102     while ((option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
103         hasOption = true;
104         if (option == '?') {
105             CheckPublishOpt();
106             result = ERR_INVALID_VALUE;
107             return;
108         }
109         switch (option) {
110             case 'h':
111                 result = ERR_INVALID_VALUE;
112                 break;
113             case 'e':
114                 cmdInfo.action = optarg;
115                 break;
116             case 's':
117                 cmdInfo.isSticky = true;
118                 break;
119             case 'o':
120                 cmdInfo.isOrdered = true;
121                 break;
122             case 'c':
123                 cmdInfo.code = atoi(optarg);
124                 break;
125             case 'd':
126                 cmdInfo.data = optarg;
127                 break;
128             case 'u':
129                 cmdInfo.userId = atoi(optarg);
130                 break;
131             default:
132                 break;
133         }
134     }
135 }
136 
CheckPublishOpt()137 void CommonEventCommand::CheckPublishOpt()
138 {
139     switch (optopt) {
140         case 'e': {
141             resultReceiver_.append("error: option 'e' requires a value.\n");
142             break;
143         }
144         case 'c': {
145             resultReceiver_.append("error: option 'c' requires a value.\n");
146             break;
147         }
148         case 'd': {
149             resultReceiver_.append("error: option 'd' requires a value.\n");
150             break;
151         }
152         case 'u': {
153             resultReceiver_.append("error: option 'u' requires a value.\n");
154             break;
155         }
156         default: {
157             resultReceiver_.append("error: unknown option.\n");
158             break;
159         }
160     }
161 }
162 
RunAsDumpCommand()163 ErrCode CommonEventCommand::RunAsDumpCommand()
164 {
165 #ifdef CEM_BUILD_VARIANT_USER
166      resultReceiver_.append(USER_DUMP_COMMON_EVENT_NG);
167      return ERR_INVALID_VALUE;
168 #endif
169     EVENT_LOGI("enter");
170     ErrCode result = ERR_OK;
171     bool hasOption = false;
172     DumpCmdInfo cmdInfo;
173     SetDumpCmdInfo(cmdInfo, result, hasOption);
174     if (!hasOption) {
175         resultReceiver_.append(HELP_MSG_NO_OPTION);
176         resultReceiver_.append(HELP_MSG_DUMP);
177         return ERR_INVALID_VALUE;
178     }
179     if (result == ERR_OK) {
180         std::vector<std::string> dumpResults;
181         bool dumpResult = CommonEvent::GetInstance()->DumpState(
182             static_cast<int32_t>(cmdInfo.eventType), cmdInfo.action, cmdInfo.userId, dumpResults);
183         if (dumpResult) {
184             EVENT_LOGI("event size %{public}zu", dumpResults.size());
185             for (const auto &it : dumpResults) {
186                 EVENT_LOGI("event %{public}s", it.c_str());
187                 resultReceiver_.append(it + "\n");
188             }
189         } else {
190             resultReceiver_ = STRING_DUMP_COMMON_EVENT_NG;
191         }
192     } else {
193         resultReceiver_.append(HELP_MSG_DUMP);
194     }
195     return result;
196 }
197 
SetDumpCmdInfo(DumpCmdInfo & cmdInfo,ErrCode & result,bool & hasOption)198 void CommonEventCommand::SetDumpCmdInfo(DumpCmdInfo &cmdInfo, ErrCode &result, bool &hasOption)
199 {
200     int option;
201     while ((option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
202         hasOption = true;
203         if (option == '?') {
204             CheckDumpOpt();
205             result = ERR_INVALID_VALUE;
206             return;
207         }
208         switch (option) {
209             case 'h':
210                 result = ERR_INVALID_VALUE;
211                 break;
212             case 'e':
213                 cmdInfo.action = optarg;
214                 break;
215             case 'u':
216                 cmdInfo.userId = atoi(optarg);
217                 break;
218             case 'p':
219                 CheckDumpEventType(cmdInfo, result);
220                 break;
221             default:
222                 break;
223         }
224     }
225 }
226 
CheckDumpOpt()227 void CommonEventCommand::CheckDumpOpt()
228 {
229     switch (optopt) {
230         case 'e':
231             resultReceiver_.append("error: option 'e' requires a value.\n");
232             break;
233         case 'u':
234             resultReceiver_.append("error: option 'u' requires a value.\n");
235             break;
236         default:
237             resultReceiver_.append("error: unknown option.\n");
238             break;
239     }
240 }
241 
CheckDumpEventType(DumpCmdInfo & cmdInfo,ErrCode & result)242 void CommonEventCommand::CheckDumpEventType(DumpCmdInfo &cmdInfo, ErrCode &result)
243 {
244     if (strcmp(optarg, "subscriber") == 0) {
245         cmdInfo.eventType = DumpEventType::SUBSCRIBER;
246     } else if (strcmp(optarg, "sticky") == 0) {
247         cmdInfo.eventType = DumpEventType::STICKY;
248     } else if (strcmp(optarg, "pending") == 0) {
249         cmdInfo.eventType = DumpEventType::PENDING;
250     } else if (strcmp(optarg, "history") == 0) {
251         cmdInfo.eventType = DumpEventType::HISTORY;
252     } else {
253         resultReceiver_.append("error: option 'p' requires a value.\n");
254         result = ERR_INVALID_VALUE;
255     }
256 }
257 }  // namespace EventFwk
258 }  // namespace OHOS
259